diff options
Diffstat (limited to 'mysys')
49 files changed, 1768 insertions, 886 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 22b46e3893a..22d758d45a5 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -17,6 +17,7 @@ INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys) SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c + get_password.c errors.c hash.c list.c mf_cache.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c @@ -40,8 +41,9 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c my_default.c lf_alloc-pin.c lf_dynarray.c lf_hash.c safemalloc.c my_new.cc my_atomic.c my_getncpus.c my_safehash.c my_chmod.c my_rnd.c - my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c + my_uuid.c wqueue.c waiting_threads.c ma_dyncol.c ../sql-common/my_time.c my_rdtsc.c my_context.c psi_noop.c + my_atomic_writes.c file_logger.c my_dlerror.c) IF (WIN32) @@ -62,7 +64,7 @@ IF(CMAKE_SYSTEM_NAME MATCHES "SunOS" AND CMAKE_C_COMPILER_ID MATCHES "SunPro") PROPERTIES COMPILE_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/my_timer_cycles.il") ENDIF() -IF(HAVE_LARGE_PAGES) +IF(HAVE_LINUX_LARGE_PAGES) SET(MYSYS_SOURCES ${MYSYS_SOURCES} my_largepage.c) ENDIF() @@ -71,8 +73,8 @@ IF(HAVE_MLOCK) ENDIF() ADD_CONVENIENCE_LIBRARY(mysys ${MYSYS_SOURCES}) -TARGET_LINK_LIBRARIES(mysys dbug strings mysys_ssl ${ZLIB_LIBRARY} - ${LIBNSL} ${LIBM} ${LIBRT} ${LIBDL} ${LIBSOCKET} ${LIBEXECINFO}) +TARGET_LINK_LIBRARIES(mysys dbug strings + ${ZLIB_LIBRARY} ${LIBNSL} ${LIBM} ${LIBRT} ${LIBDL} ${LIBSOCKET} ${LIBEXECINFO} ${CRC32_VPMSUM_LIBRARY}) DTRACE_INSTRUMENT(mysys) IF(HAVE_BFD_H) @@ -96,6 +98,10 @@ ADD_EXECUTABLE(thr_timer thr_timer.c) TARGET_LINK_LIBRARIES(thr_timer mysys) SET_TARGET_PROPERTIES(thr_timer PROPERTIES COMPILE_FLAGS "-DMAIN") +ADD_EXECUTABLE(test_hash hash.c) +TARGET_LINK_LIBRARIES(test_hash mysys) +SET_TARGET_PROPERTIES(test_hash PROPERTIES COMPILE_FLAGS "-DMAIN") + IF(MSVC) INSTALL_DEBUG_TARGET(mysys DESTINATION ${INSTALL_LIBDIR}/debug) ENDIF() diff --git a/mysys/base64.c b/mysys/base64.c index d0569d34855..d46c9a22d2b 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -25,22 +25,22 @@ static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789+/"; /** - * Maximum length base64_needed_encoded_length() + * Maximum length my_base64_needed_encoded_length() * can handle without signed integer overflow. */ int -base64_encode_max_arg_length() +my_base64_encode_max_arg_length() { /* - base64_needed_encoded_length(1589695686) -> 2147483646 (7FFFFFFE) - base64_needed_encoded_length(1589695687) -> -2147483645 + my_base64_needed_encoded_length(1589695686) -> 2147483646 (7FFFFFFE) + my_base64_needed_encoded_length(1589695687) -> -2147483645 */ return 0x5EC0D4C6; /* 1589695686 */ } int -base64_needed_encoded_length(int length_of_data) +my_base64_needed_encoded_length(int length_of_data) { int nb_base64_chars; nb_base64_chars= (length_of_data + 2) / 3 * 4; @@ -53,17 +53,17 @@ base64_needed_encoded_length(int length_of_data) /** - * Maximum length supported by base64_decode(). + * Maximum length supported by my_base64_decode(). */ int -base64_decode_max_arg_length() +my_base64_decode_max_arg_length() { return 0x7FFFFFFF; } int -base64_needed_decoded_length(int length_of_encoded_data) +my_base64_needed_decoded_length(int length_of_encoded_data) { return (int) ((longlong) length_of_encoded_data + 3) / 4 * 3; } @@ -73,7 +73,7 @@ base64_needed_decoded_length(int length_of_encoded_data) Encode a data as base64. Note: We require that dst is pre-allocated to correct size. - See base64_needed_encoded_length(). + See my_base64_needed_encoded_length(). Note: We add line separators every 76 characters. @@ -82,7 +82,7 @@ base64_needed_decoded_length(int length_of_encoded_data) */ int -base64_encode(const void *src, size_t src_len, char *dst) +my_base64_encode(const void *src, size_t src_len, char *dst) { const unsigned char *s= (const unsigned char*)src; size_t i= 0; @@ -298,7 +298,7 @@ my_base64_decoder_getch(MY_BASE64_DECODER *decoder) * the last read character, even in the presence of error. * * Note: 'dst' must have sufficient space to store the decoded data. - * Use base64_needed_decoded_length() to calculate the correct space size. + * Use my_base64_needed_decoded_length() to calculate the correct space size. * * Note: we allow spaces and line separators at any position. * @@ -312,7 +312,7 @@ my_base64_decoder_getch(MY_BASE64_DECODER *decoder) * @return Number of bytes written at 'dst', or -1 in case of failure */ int -base64_decode(const char *src_base, size_t len, +my_base64_decode(const char *src_base, size_t len, void *dst, const char **end_ptr, int flags) { char *d= (char*) dst; @@ -396,18 +396,18 @@ main(void) } /* Encode */ - needed_length= base64_needed_encoded_length(src_len); + needed_length= my_base64_needed_encoded_length(src_len); str= (char *) malloc(needed_length); require(str); for (k= 0; k < needed_length; k++) str[k]= 0xff; /* Fill memory to check correct NUL termination */ - require(base64_encode(src, src_len, str) == 0); + require(my_base64_encode(src, src_len, str) == 0); require(needed_length == strlen(str) + 1); /* Decode */ - dst= (char *) malloc(base64_needed_decoded_length(strlen(str))); + dst= (char *) malloc(my_base64_needed_decoded_length(strlen(str))); require(dst); - dst_len= base64_decode(str, strlen(str), dst, NULL); + dst_len= my_base64_decode(str, strlen(str), dst, NULL); require(dst_len == src_len); if (memcmp(src, dst, src_len) != 0) diff --git a/mysys/charset-def.c b/mysys/charset-def.c index 8539f7b2803..b4317806762 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -50,6 +50,7 @@ extern struct charset_info_st my_charset_ucs2_vietnamese_ci; extern struct charset_info_st my_charset_ucs2_croatian_uca_ci; extern struct charset_info_st my_charset_ucs2_myanmar_uca_ci; extern struct charset_info_st my_charset_ucs2_thai_520_w2; +extern struct charset_info_st my_charset_ucs2_unicode_520_nopad_ci; #endif @@ -80,6 +81,7 @@ extern struct charset_info_st my_charset_utf32_vietnamese_ci; extern struct charset_info_st my_charset_utf32_croatian_uca_ci; extern struct charset_info_st my_charset_utf32_myanmar_uca_ci; extern struct charset_info_st my_charset_utf32_thai_520_w2; +extern struct charset_info_st my_charset_utf32_unicode_520_nopad_ci; #endif /* HAVE_CHARSET_utf32 */ @@ -110,6 +112,7 @@ extern struct charset_info_st my_charset_utf16_vietnamese_ci; extern struct charset_info_st my_charset_utf16_croatian_uca_ci; extern struct charset_info_st my_charset_utf16_myanmar_uca_ci; extern struct charset_info_st my_charset_utf16_thai_520_w2; +extern struct charset_info_st my_charset_utf16_unicode_520_nopad_ci; #endif /* HAVE_CHARSET_utf16 */ @@ -143,6 +146,7 @@ extern struct charset_info_st my_charset_utf8_thai_520_w2; #ifdef HAVE_UTF8_GENERAL_CS extern struct charset_info_st my_charset_utf8_general_cs; #endif +extern struct charset_info_st my_charset_utf8_unicode_520_nopad_ci; #endif #ifdef HAVE_CHARSET_utf8mb4 @@ -172,6 +176,7 @@ extern struct charset_info_st my_charset_utf8mb4_vietnamese_ci; extern struct charset_info_st my_charset_utf8mb4_croatian_uca_ci; extern struct charset_info_st my_charset_utf8mb4_myanmar_uca_ci; extern struct charset_info_st my_charset_utf8mb4_thai_520_w2; +extern struct charset_info_st my_charset_utf8mb4_unicode_520_nopad_ci; #endif /* HAVE_CHARSET_utf8mb4 */ #endif /* HAVE_UCA_COLLATIONS */ @@ -184,12 +189,16 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_filename); add_compiled_collation(&my_charset_latin1); + add_compiled_collation(&my_charset_latin1_nopad); add_compiled_collation(&my_charset_latin1_bin); + add_compiled_collation(&my_charset_latin1_nopad_bin); add_compiled_collation(&my_charset_latin1_german2_ci); #ifdef HAVE_CHARSET_big5 add_compiled_collation(&my_charset_big5_chinese_ci); add_compiled_collation(&my_charset_big5_bin); + add_compiled_collation(&my_charset_big5_chinese_nopad_ci); + add_compiled_collation(&my_charset_big5_nopad_bin); #endif #ifdef HAVE_CHARSET_cp1250 @@ -199,6 +208,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) #ifdef HAVE_CHARSET_cp932 add_compiled_collation(&my_charset_cp932_japanese_ci); add_compiled_collation(&my_charset_cp932_bin); + add_compiled_collation(&my_charset_cp932_japanese_nopad_ci); + add_compiled_collation(&my_charset_cp932_nopad_bin); #endif #ifdef HAVE_CHARSET_latin2 @@ -208,36 +219,50 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) #ifdef HAVE_CHARSET_eucjpms add_compiled_collation(&my_charset_eucjpms_japanese_ci); add_compiled_collation(&my_charset_eucjpms_bin); + add_compiled_collation(&my_charset_eucjpms_japanese_nopad_ci); + add_compiled_collation(&my_charset_eucjpms_nopad_bin); #endif #ifdef HAVE_CHARSET_euckr add_compiled_collation(&my_charset_euckr_korean_ci); add_compiled_collation(&my_charset_euckr_bin); + add_compiled_collation(&my_charset_euckr_korean_nopad_ci); + add_compiled_collation(&my_charset_euckr_nopad_bin); #endif #ifdef HAVE_CHARSET_gb2312 add_compiled_collation(&my_charset_gb2312_chinese_ci); add_compiled_collation(&my_charset_gb2312_bin); + add_compiled_collation(&my_charset_gb2312_chinese_nopad_ci); + add_compiled_collation(&my_charset_gb2312_nopad_bin); #endif #ifdef HAVE_CHARSET_gbk add_compiled_collation(&my_charset_gbk_chinese_ci); add_compiled_collation(&my_charset_gbk_bin); + add_compiled_collation(&my_charset_gbk_chinese_nopad_ci); + add_compiled_collation(&my_charset_gbk_nopad_bin); #endif #ifdef HAVE_CHARSET_sjis add_compiled_collation(&my_charset_sjis_japanese_ci); add_compiled_collation(&my_charset_sjis_bin); + add_compiled_collation(&my_charset_sjis_japanese_nopad_ci); + add_compiled_collation(&my_charset_sjis_nopad_bin); #endif #ifdef HAVE_CHARSET_tis620 add_compiled_collation(&my_charset_tis620_thai_ci); add_compiled_collation(&my_charset_tis620_bin); + add_compiled_collation(&my_charset_tis620_thai_nopad_ci); + add_compiled_collation(&my_charset_tis620_nopad_bin); #endif #ifdef HAVE_CHARSET_ucs2 add_compiled_collation(&my_charset_ucs2_general_ci); add_compiled_collation(&my_charset_ucs2_bin); + add_compiled_collation(&my_charset_ucs2_general_nopad_ci); + add_compiled_collation(&my_charset_ucs2_nopad_bin); add_compiled_collation(&my_charset_ucs2_general_mysql500_ci); #ifdef HAVE_UCA_COLLATIONS add_compiled_collation(&my_charset_ucs2_unicode_ci); @@ -267,17 +292,23 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_ucs2_croatian_uca_ci); add_compiled_collation(&my_charset_ucs2_myanmar_uca_ci); add_compiled_collation(&my_charset_ucs2_thai_520_w2); + add_compiled_collation(&my_charset_ucs2_unicode_nopad_ci); + add_compiled_collation(&my_charset_ucs2_unicode_520_nopad_ci); #endif #endif #ifdef HAVE_CHARSET_ujis add_compiled_collation(&my_charset_ujis_japanese_ci); add_compiled_collation(&my_charset_ujis_bin); + add_compiled_collation(&my_charset_ujis_japanese_nopad_ci); + add_compiled_collation(&my_charset_ujis_nopad_bin); #endif #ifdef HAVE_CHARSET_utf8 add_compiled_collation(&my_charset_utf8_general_ci); + add_compiled_collation(&my_charset_utf8_general_nopad_ci); add_compiled_collation(&my_charset_utf8_bin); + add_compiled_collation(&my_charset_utf8_nopad_bin); add_compiled_collation(&my_charset_utf8_general_mysql500_ci); #ifdef HAVE_UTF8_GENERAL_CS add_compiled_collation(&my_charset_utf8_general_cs); @@ -310,6 +341,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf8_croatian_uca_ci); add_compiled_collation(&my_charset_utf8_myanmar_uca_ci); add_compiled_collation(&my_charset_utf8_thai_520_w2); + add_compiled_collation(&my_charset_utf8_unicode_nopad_ci); + add_compiled_collation(&my_charset_utf8_unicode_520_nopad_ci); #endif #endif /* HAVE_CHARSET_utf8 */ @@ -317,6 +350,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) #ifdef HAVE_CHARSET_utf8mb4 add_compiled_collation(&my_charset_utf8mb4_general_ci); add_compiled_collation(&my_charset_utf8mb4_bin); + add_compiled_collation(&my_charset_utf8mb4_general_nopad_ci); + add_compiled_collation(&my_charset_utf8mb4_nopad_bin); #ifdef HAVE_UCA_COLLATIONS add_compiled_collation(&my_charset_utf8mb4_unicode_ci); add_compiled_collation(&my_charset_utf8mb4_german2_uca_ci); @@ -345,6 +380,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf8mb4_croatian_uca_ci); add_compiled_collation(&my_charset_utf8mb4_myanmar_uca_ci); add_compiled_collation(&my_charset_utf8mb4_thai_520_w2); + add_compiled_collation(&my_charset_utf8mb4_unicode_nopad_ci); + add_compiled_collation(&my_charset_utf8mb4_unicode_520_nopad_ci); #endif /* HAVE_UCA_COLLATIONS */ #endif /* HAVE_CHARSET_utf8mb4 */ @@ -354,6 +391,10 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf16_bin); add_compiled_collation(&my_charset_utf16le_general_ci); add_compiled_collation(&my_charset_utf16le_bin); + add_compiled_collation(&my_charset_utf16_general_nopad_ci); + add_compiled_collation(&my_charset_utf16_nopad_bin); + add_compiled_collation(&my_charset_utf16le_general_nopad_ci); + add_compiled_collation(&my_charset_utf16le_nopad_bin); #ifdef HAVE_UCA_COLLATIONS add_compiled_collation(&my_charset_utf16_unicode_ci); add_compiled_collation(&my_charset_utf16_german2_uca_ci); @@ -382,6 +423,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf16_croatian_uca_ci); add_compiled_collation(&my_charset_utf16_myanmar_uca_ci); add_compiled_collation(&my_charset_utf16_thai_520_w2); + add_compiled_collation(&my_charset_utf16_unicode_nopad_ci); + add_compiled_collation(&my_charset_utf16_unicode_520_nopad_ci); #endif /* HAVE_UCA_COLLATIONS */ #endif /* HAVE_CHARSET_utf16 */ @@ -389,6 +432,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) #ifdef HAVE_CHARSET_utf32 add_compiled_collation(&my_charset_utf32_general_ci); add_compiled_collation(&my_charset_utf32_bin); + add_compiled_collation(&my_charset_utf32_general_nopad_ci); + add_compiled_collation(&my_charset_utf32_nopad_bin); #ifdef HAVE_UCA_COLLATIONS add_compiled_collation(&my_charset_utf32_unicode_ci); add_compiled_collation(&my_charset_utf32_german2_uca_ci); @@ -417,6 +462,8 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) add_compiled_collation(&my_charset_utf32_croatian_uca_ci); add_compiled_collation(&my_charset_utf32_myanmar_uca_ci); add_compiled_collation(&my_charset_utf32_thai_520_w2); + add_compiled_collation(&my_charset_utf32_unicode_nopad_ci); + add_compiled_collation(&my_charset_utf32_unicode_520_nopad_ci); #endif /* HAVE_UCA_COLLATIONS */ #endif /* HAVE_CHARSET_utf32 */ diff --git a/mysys/charset.c b/mysys/charset.c index 31bde080dc2..f44dc7606c1 100644 --- a/mysys/charset.c +++ b/mysys/charset.c @@ -20,7 +20,12 @@ #include <m_string.h> #include <my_dir.h> #include <my_xml.h> - +#ifdef HAVE_LANGINFO_H +#include <langinfo.h> +#endif +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif /* The code below implements this functionality: @@ -54,6 +59,12 @@ get_collation_number_internal(const char *name) } +static my_bool is_multi_byte_ident(CHARSET_INFO *cs, uchar ch) +{ + int chlen= my_charlen(cs, (const char *) &ch, (const char *) &ch + 1); + return MY_CS_IS_TOOSMALL(chlen) ? TRUE : FALSE; +} + static my_bool init_state_maps(struct charset_info_st *cs) { uint i; @@ -73,10 +84,8 @@ static my_bool init_state_maps(struct charset_info_st *cs) state_map[i]=(uchar) MY_LEX_IDENT; else if (my_isdigit(cs,i)) state_map[i]=(uchar) MY_LEX_NUMBER_IDENT; -#if defined(USE_MB) && defined(USE_MB_IDENT) - else if (my_mbcharlen(cs, i)>1) + else if (is_multi_byte_ident(cs, i)) state_map[i]=(uchar) MY_LEX_IDENT; -#endif else if (my_isspace(cs,i)) state_map[i]=(uchar) MY_LEX_SKIP; else @@ -119,13 +128,21 @@ static my_bool init_state_maps(struct charset_info_st *cs) } +static MY_COLLATION_HANDLER *get_simple_collation_handler_by_flags(uint flags) +{ + return flags & MY_CS_BINSORT ? + (flags & MY_CS_NOPAD ? + &my_collation_8bit_nopad_bin_handler : + &my_collation_8bit_bin_handler) : + (flags & MY_CS_NOPAD ? + &my_collation_8bit_simple_nopad_ci_handler : + &my_collation_8bit_simple_ci_handler); +} + + static void simple_cs_init_functions(struct charset_info_st *cs) { - if (cs->state & MY_CS_BINSORT) - cs->coll= &my_collation_8bit_bin_handler; - else - cs->coll= &my_collation_8bit_simple_ci_handler; - + cs->coll= get_simple_collation_handler_by_flags(cs->state); cs->cset= &my_charset_8bit_handler; } @@ -193,23 +210,91 @@ err: } +static my_bool simple_8bit_charset_data_is_full(CHARSET_INFO *cs) +{ + return cs->ctype && cs->to_upper && cs->to_lower && cs->tab_to_uni; +} + + +/** + Inherit missing 8bit charset data from another collation. + Arrays pointed by refcs must be in the permanent memory already, + e.g. static memory, or allocated by my_once_xxx(). +*/ +static void +inherit_charset_data(struct charset_info_st *cs, CHARSET_INFO *refcs) +{ + if (!cs->to_upper) + cs->to_upper= refcs->to_upper; + if (!cs->to_lower) + cs->to_lower= refcs->to_lower; + if (!cs->ctype) + cs->ctype= refcs->ctype; + if (!cs->tab_to_uni) + cs->tab_to_uni= refcs->tab_to_uni; +} + + +static my_bool simple_8bit_collation_data_is_full(CHARSET_INFO *cs) +{ + return cs->sort_order || (cs->state & MY_CS_BINSORT); +} + + +/** + Inherit 8bit simple collation data from another collation. + refcs->sort_order must be in the permanent memory already, + e.g. static memory, or allocated by my_once_xxx(). +*/ +static void +inherit_collation_data(struct charset_info_st *cs, CHARSET_INFO *refcs) +{ + if (!simple_8bit_collation_data_is_full(cs)) + cs->sort_order= refcs->sort_order; +} + static my_bool simple_cs_is_full(CHARSET_INFO *cs) { - return ((cs->csname && cs->tab_to_uni && cs->ctype && cs->to_upper && - cs->to_lower) && - (cs->number && cs->name && - (cs->sort_order || (cs->state & MY_CS_BINSORT) ))); + return cs->number && cs->csname && cs->name && + simple_8bit_charset_data_is_full(cs) && + (simple_8bit_collation_data_is_full(cs) || cs->tailoring); } #if defined(HAVE_UCA_COLLATIONS) && (defined(HAVE_CHARSET_ucs2) || defined(HAVE_CHARSET_utf8)) +/** + Initialize a loaded collation. + @param [OUT] to - The new charset_info_st structure to initialize. + @param [IN] from - A template collation, to fill the missing data from. + @param [IN] loaded - The collation data loaded from the LDML file. + some data may be missing in "loaded". +*/ static void -copy_uca_collation(struct charset_info_st *to, CHARSET_INFO *from) +copy_uca_collation(struct charset_info_st *to, CHARSET_INFO *from, + CHARSET_INFO *loaded) { to->cset= from->cset; to->coll= from->coll; - to->strxfrm_multiply= from->strxfrm_multiply; + /* + Single-level UCA collation have strnxfrm_multiple=8. + In case of a multi-level UCA collation we use strnxfrm_multiply=4. + That means MY_COLLATION_HANDLER::strnfrmlen() will request the caller + to allocate a buffer smaller size for each level, for performance purpose, + and to fit longer VARCHARs to @@max_sort_length. + This makes filesort produce non-precise order for some rare Unicode + characters that produce more than 4 weights (long expansions). + UCA requires 2 bytes per weight multiplied by the number of levels. + In case of a 2-level collation, each character requires 4*2=8 bytes. + Therefore, the longest VARCHAR that fits into the default @@max_sort_length + is 1024/8=VARCHAR(128). With strnxfrm_multiply==8, only VARCHAR(64) + would fit. + Note, the built-in collation utf8_thai_520_w2 also uses strnxfrm_multiply=4, + for the same purpose. + TODO: we could add a new LDML syntax to choose strxfrm_multiply value. + */ + to->strxfrm_multiply= loaded->levels_for_order > 1 ? + 4 : from->strxfrm_multiply; to->min_sort_char= from->min_sort_char; to->max_sort_char= from->max_sort_char; to->mbminlen= from->mbminlen; @@ -256,14 +341,20 @@ static int add_collation(struct charset_info_st *cs) if (!strcmp(cs->csname,"ucs2") ) { #if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci); + copy_uca_collation(newcs, newcs->state & MY_CS_NOPAD ? + &my_charset_ucs2_unicode_nopad_ci : + &my_charset_ucs2_unicode_ci, + cs); newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; #endif } else if (!strcmp(cs->csname, "utf8") || !strcmp(cs->csname, "utf8mb3")) { #if defined (HAVE_CHARSET_utf8) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_utf8_unicode_ci); + copy_uca_collation(newcs, newcs->state & MY_CS_NOPAD ? + &my_charset_utf8_unicode_nopad_ci : + &my_charset_utf8_unicode_ci, + cs); newcs->ctype= my_charset_utf8_unicode_ci.ctype; if (init_state_maps(newcs)) return MY_XML_ERROR; @@ -272,7 +363,10 @@ static int add_collation(struct charset_info_st *cs) else if (!strcmp(cs->csname, "utf8mb4")) { #if defined (HAVE_CHARSET_utf8mb4) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_utf8mb4_unicode_ci); + copy_uca_collation(newcs, newcs->state & MY_CS_NOPAD ? + &my_charset_utf8mb4_unicode_nopad_ci : + &my_charset_utf8mb4_unicode_ci, + cs); newcs->ctype= my_charset_utf8mb4_unicode_ci.ctype; newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED; #endif @@ -280,20 +374,25 @@ static int add_collation(struct charset_info_st *cs) else if (!strcmp(cs->csname, "utf16")) { #if defined (HAVE_CHARSET_utf16) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_utf16_unicode_ci); + copy_uca_collation(newcs, newcs->state & MY_CS_NOPAD ? + &my_charset_utf16_unicode_nopad_ci : + &my_charset_utf16_unicode_ci, + cs); newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; #endif } else if (!strcmp(cs->csname, "utf32")) { #if defined (HAVE_CHARSET_utf32) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_utf32_unicode_ci); + copy_uca_collation(newcs, newcs->state & MY_CS_NOPAD ? + &my_charset_utf32_unicode_nopad_ci : + &my_charset_utf32_unicode_ci, + cs); newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; #endif } else { - const uchar *sort_order= newcs->sort_order; simple_cs_init_functions(newcs); newcs->mbminlen= 1; newcs->mbmaxlen= 1; @@ -303,21 +402,6 @@ static int add_collation(struct charset_info_st *cs) newcs->state |= MY_CS_LOADED; } newcs->state|= MY_CS_AVAILABLE; - - /* - Check if case sensitive sort order: A < a < B. - We need MY_CS_FLAG for regex library, and for - case sensitivity flag for 5.0 client protocol, - to support isCaseSensitive() method in JDBC driver - */ - if (sort_order && sort_order['A'] < sort_order['a'] && - sort_order['a'] < sort_order['B']) - newcs->state|= MY_CS_CSSORT; - - if (my_charset_is_8bit_pure_ascii(newcs)) - newcs->state|= MY_CS_PUREASCII; - if (!my_charset_is_ascii_compatible(cs)) - newcs->state|= MY_CS_NONASCII; } } else @@ -348,7 +432,7 @@ static int add_collation(struct charset_info_st *cs) cs->name= NULL; cs->state= 0; cs->sort_order= NULL; - cs->state= 0; + cs->tailoring= NULL; } return MY_XML_OK; } @@ -545,6 +629,7 @@ static void init_available_charsets(void) { if (*cs) { + DBUG_ASSERT(cs[0]->mbmaxlen <= MY_CS_MBMAXLEN); if (cs[0]->ctype) if (init_state_maps(*cs)) *cs= NULL; @@ -642,6 +727,39 @@ const char *get_charset_name(uint charset_number) } +static CHARSET_INFO *inheritance_source_by_id(CHARSET_INFO *cs, uint refid) +{ + CHARSET_INFO *refcs; + return refid && refid != cs->number && + (refcs= all_charsets[refid]) && + (refcs->state & MY_CS_AVAILABLE) ? refcs : NULL; +} + + +static CHARSET_INFO *find_collation_data_inheritance_source(CHARSET_INFO *cs) +{ + const char *beg, *end; + if (cs->tailoring && + !strncmp(cs->tailoring, "[import ", 8) && + (end= strchr(cs->tailoring + 8, ']')) && + (beg= cs->tailoring + 8) + MY_CS_NAME_SIZE > end) + { + char name[MY_CS_NAME_SIZE + 1]; + memcpy(name, beg, end - beg); + name[end - beg]= '\0'; + return inheritance_source_by_id(cs, get_collation_number(name)); + } + return NULL; +} + + +static CHARSET_INFO *find_charset_data_inheritance_source(CHARSET_INFO *cs) +{ + uint refid= get_charset_number_internal(cs->csname, MY_CS_PRIMARY); + return inheritance_source_by_id(cs, refid); +} + + static CHARSET_INFO * get_internal_charset(MY_CHARSET_LOADER *loader, uint cs_number, myf flags) { @@ -676,6 +794,19 @@ get_internal_charset(MY_CHARSET_LOADER *loader, uint cs_number, myf flags) { if (!(cs->state & MY_CS_READY)) { + if (!simple_8bit_charset_data_is_full(cs)) + { + CHARSET_INFO *refcs= find_charset_data_inheritance_source(cs); + if (refcs) + inherit_charset_data(cs, refcs); + } + if (!simple_8bit_collation_data_is_full(cs)) + { + CHARSET_INFO *refcl= find_collation_data_inheritance_source(cs); + if (refcl) + inherit_collation_data(cs, refcl); + } + if ((cs->cset->init && cs->cset->init(cs, loader)) || (cs->coll->init && cs->coll->init(cs, loader))) { @@ -901,15 +1032,13 @@ size_t escape_string_for_mysql(CHARSET_INFO *charset_info, const char *to_start= to; const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); my_bool overflow= FALSE; -#ifdef USE_MB - my_bool use_mb_flag= use_mb(charset_info); -#endif for (end= from + length; from < end; from++) { char escape= 0; #ifdef USE_MB - int tmp_length; - if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) + int tmp_length= use_mb(charset_info) ? my_charlen(charset_info, from, end) : + 1; + if (tmp_length > 1) { if (to + tmp_length > to_end) { @@ -932,7 +1061,7 @@ size_t escape_string_for_mysql(CHARSET_INFO *charset_info, multi-byte character into a valid one. For example, 0xbf27 is not a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \) */ - if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1) + if (tmp_length < 1) /* Bad byte sequence */ escape= *from; else #endif @@ -1092,3 +1221,214 @@ size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info, *to= 0; return overflow ? (ulong)~0 : (ulong) (to - to_start); } + + +typedef enum my_cs_match_type_enum +{ + /* MySQL and OS charsets are fully compatible */ + my_cs_exact, + /* MySQL charset is very close to OS charset */ + my_cs_approx, + /* + MySQL knows this charset, but it is not supported as client character set. + */ + my_cs_unsupp +} my_cs_match_type; + + +typedef struct str2str_st +{ + const char* os_name; + const char* my_name; + my_cs_match_type param; +} MY_CSET_OS_NAME; + +static const MY_CSET_OS_NAME charsets[] = +{ +#ifdef _WIN32 + {"cp437", "cp850", my_cs_approx}, + {"cp850", "cp850", my_cs_exact}, + {"cp852", "cp852", my_cs_exact}, + {"cp858", "cp850", my_cs_approx}, + {"cp866", "cp866", my_cs_exact}, + {"cp874", "tis620", my_cs_approx}, + {"cp932", "cp932", my_cs_exact}, + {"cp936", "gbk", my_cs_approx}, + {"cp949", "euckr", my_cs_approx}, + {"cp950", "big5", my_cs_exact}, + {"cp1200", "utf16le", my_cs_unsupp}, + {"cp1201", "utf16", my_cs_unsupp}, + {"cp1250", "cp1250", my_cs_exact}, + {"cp1251", "cp1251", my_cs_exact}, + {"cp1252", "latin1", my_cs_exact}, + {"cp1253", "greek", my_cs_exact}, + {"cp1254", "latin5", my_cs_exact}, + {"cp1255", "hebrew", my_cs_approx}, + {"cp1256", "cp1256", my_cs_exact}, + {"cp1257", "cp1257", my_cs_exact}, + {"cp10000", "macroman", my_cs_exact}, + {"cp10001", "sjis", my_cs_approx}, + {"cp10002", "big5", my_cs_approx}, + {"cp10008", "gb2312", my_cs_approx}, + {"cp10021", "tis620", my_cs_approx}, + {"cp10029", "macce", my_cs_exact}, + {"cp12001", "utf32", my_cs_unsupp}, + {"cp20107", "swe7", my_cs_exact}, + {"cp20127", "latin1", my_cs_approx}, + {"cp20866", "koi8r", my_cs_exact}, + {"cp20932", "ujis", my_cs_exact}, + {"cp20936", "gb2312", my_cs_approx}, + {"cp20949", "euckr", my_cs_approx}, + {"cp21866", "koi8u", my_cs_exact}, + {"cp28591", "latin1", my_cs_approx}, + {"cp28592", "latin2", my_cs_exact}, + {"cp28597", "greek", my_cs_exact}, + {"cp28598", "hebrew", my_cs_exact}, + {"cp28599", "latin5", my_cs_exact}, + {"cp28603", "latin7", my_cs_exact}, +#ifdef UNCOMMENT_THIS_WHEN_WL_4579_IS_DONE + {"cp28605", "latin9", my_cs_exact}, +#endif + {"cp38598", "hebrew", my_cs_exact}, + {"cp51932", "ujis", my_cs_exact}, + {"cp51936", "gb2312", my_cs_exact}, + {"cp51949", "euckr", my_cs_exact}, + {"cp51950", "big5", my_cs_exact}, +#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE + {"cp54936", "gb18030", my_cs_exact}, +#endif + {"cp65001", "utf8", my_cs_exact}, + +#else /* not Windows */ + + {"646", "latin1", my_cs_approx}, /* Default on Solaris */ + {"ANSI_X3.4-1968", "latin1", my_cs_approx}, + {"ansi1251", "cp1251", my_cs_exact}, + {"armscii8", "armscii8", my_cs_exact}, + {"armscii-8", "armscii8", my_cs_exact}, + {"ASCII", "latin1", my_cs_approx}, + {"Big5", "big5", my_cs_exact}, + {"cp1251", "cp1251", my_cs_exact}, + {"cp1255", "hebrew", my_cs_approx}, + {"CP866", "cp866", my_cs_exact}, + {"eucCN", "gb2312", my_cs_exact}, + {"euc-CN", "gb2312", my_cs_exact}, + {"eucJP", "ujis", my_cs_exact}, + {"euc-JP", "ujis", my_cs_exact}, + {"eucKR", "euckr", my_cs_exact}, + {"euc-KR", "euckr", my_cs_exact}, +#ifdef UNCOMMENT_THIS_WHEN_WL_WL_4024_IS_DONE + {"gb18030", "gb18030", my_cs_exact}, +#endif + {"gb2312", "gb2312", my_cs_exact}, + {"gbk", "gbk", my_cs_exact}, + {"georgianps", "geostd8", my_cs_exact}, + {"georgian-ps", "geostd8", my_cs_exact}, + {"IBM-1252", "cp1252", my_cs_exact}, + + {"iso88591", "latin1", my_cs_approx}, + {"ISO_8859-1", "latin1", my_cs_approx}, + {"ISO8859-1", "latin1", my_cs_approx}, + {"ISO-8859-1", "latin1", my_cs_approx}, + + {"iso885913", "latin7", my_cs_exact}, + {"ISO_8859-13", "latin7", my_cs_exact}, + {"ISO8859-13", "latin7", my_cs_exact}, + {"ISO-8859-13", "latin7", my_cs_exact}, + +#ifdef UNCOMMENT_THIS_WHEN_WL_4579_IS_DONE + {"iso885915", "latin9", my_cs_exact}, + {"ISO_8859-15", "latin9", my_cs_exact}, + {"ISO8859-15", "latin9", my_cs_exact}, + {"ISO-8859-15", "latin9", my_cs_exact}, +#endif + + {"iso88592", "latin2", my_cs_exact}, + {"ISO_8859-2", "latin2", my_cs_exact}, + {"ISO8859-2", "latin2", my_cs_exact}, + {"ISO-8859-2", "latin2", my_cs_exact}, + + {"iso88597", "greek", my_cs_exact}, + {"ISO_8859-7", "greek", my_cs_exact}, + {"ISO8859-7", "greek", my_cs_exact}, + {"ISO-8859-7", "greek", my_cs_exact}, + + {"iso88598", "hebrew", my_cs_exact}, + {"ISO_8859-8", "hebrew", my_cs_exact}, + {"ISO8859-8", "hebrew", my_cs_exact}, + {"ISO-8859-8", "hebrew", my_cs_exact}, + + {"iso88599", "latin5", my_cs_exact}, + {"ISO_8859-9", "latin5", my_cs_exact}, + {"ISO8859-9", "latin5", my_cs_exact}, + {"ISO-8859-9", "latin5", my_cs_exact}, + + {"koi8r", "koi8r", my_cs_exact}, + {"KOI8-R", "koi8r", my_cs_exact}, + {"koi8u", "koi8u", my_cs_exact}, + {"KOI8-U", "koi8u", my_cs_exact}, + + {"roman8", "hp8", my_cs_exact}, /* Default on HP UX */ + + {"Shift_JIS", "sjis", my_cs_exact}, + {"SJIS", "sjis", my_cs_exact}, + {"shiftjisx0213", "sjis", my_cs_exact}, + + {"tis620", "tis620", my_cs_exact}, + {"tis-620", "tis620", my_cs_exact}, + + {"ujis", "ujis", my_cs_exact}, + + {"US-ASCII", "latin1", my_cs_approx}, + + {"utf8", "utf8", my_cs_exact}, + {"utf-8", "utf8", my_cs_exact}, +#endif + {NULL, NULL, 0} +}; + + +static const char* +my_os_charset_to_mysql_charset(const char* csname) +{ + const MY_CSET_OS_NAME* csp; + for (csp = charsets; csp->os_name; csp++) + { + if (!strcasecmp(csp->os_name, csname)) + { + switch (csp->param) + { + case my_cs_exact: + return csp->my_name; + + case my_cs_approx: + /* + Maybe we should print a warning eventually: + character set correspondence is not exact. + */ + return csp->my_name; + + default: + return NULL; + } + } + } + return NULL; +} + +const char* my_default_csname() +{ + const char* csname = NULL; +#ifdef _WIN32 + char cpbuf[64]; + int cp = GetConsoleCP(); + if (cp == 0) + cp = GetACP(); + snprintf(cpbuf, sizeof(cpbuf), "cp%d", (int)cp); + csname = my_os_charset_to_mysql_charset(cpbuf); +#elif defined(HAVE_SETLOCALE) && defined(HAVE_NL_LANGINFO) + if (setlocale(LC_CTYPE, "") && (csname = nl_langinfo(CODESET))) + csname = my_os_charset_to_mysql_charset(csname); +#endif + return csname ? csname : MYSQL_DEFAULT_CHARSET_NAME; +}
\ No newline at end of file diff --git a/mysys/checksum.c b/mysys/checksum.c index e48535813d3..91e681d0db4 100644 --- a/mysys/checksum.c +++ b/mysys/checksum.c @@ -30,7 +30,13 @@ ha_checksum my_checksum(ha_checksum crc, const uchar *pos, size_t length) { +#ifdef HAVE_CRC32_VPMSUM + extern unsigned int crc32ieee_vpmsum(unsigned int crc, const unsigned char *p, + unsigned long len); + crc= (ha_checksum) crc32ieee_vpmsum((uint) crc, pos, (uint) length); +#else crc= (ha_checksum) crc32((uint)crc, pos, (uint) length); +#endif DBUG_PRINT("info", ("crc: %lu", (ulong) crc)); return crc; } diff --git a/mysys/errors.c b/mysys/errors.c index 786ad9afb3a..1b7a55eb1e5 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -118,7 +118,7 @@ void wait_for_free_space(const char *filename, int errors) (void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); } -const char **get_global_errmsgs() +const char **get_global_errmsgs(int nr __attribute__((unused))) { return globerrs; } diff --git a/mysys/file_logger.c b/mysys/file_logger.c index 8420ee075b0..a4cfe94a9a2 100644 --- a/mysys/file_logger.c +++ b/mysys/file_logger.c @@ -172,7 +172,7 @@ int logger_vprintf(LOGGER_HANDLE *log, const char* fmt, va_list ap) if (n_bytes >= sizeof(cvtbuf)) n_bytes= sizeof(cvtbuf) - 1; - result= my_write(log->file, (uchar *) cvtbuf, n_bytes, MYF(0)); + result= (int)my_write(log->file, (uchar *) cvtbuf, n_bytes, MYF(0)); exit: flogger_mutex_unlock(&log->lock); @@ -196,7 +196,7 @@ int logger_write(LOGGER_HANDLE *log, const char *buffer, size_t size) goto exit; /* Log rotation needed but failed */ } - result= my_write(log->file, (uchar *) buffer, size, MYF(0)); + result= (int)my_write(log->file, (uchar *) buffer, size, MYF(0)); exit: flogger_mutex_unlock(&log->lock); diff --git a/mysys/get_password.c b/mysys/get_password.c new file mode 100644 index 00000000000..04c5537fc35 --- /dev/null +++ b/mysys/get_password.c @@ -0,0 +1,208 @@ +/* Copyright (c) 2000, 2001, 2003, 2006, 2008 MySQL AB + Use is subject to license terms + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ + +/* +** Ask for a password from tty +** This is an own file to avoid conflicts with curses +*/ +#include <my_global.h> +#include <my_sys.h> +#include "mysql.h" +#include <m_string.h> +#include <m_ctype.h> + +#ifdef HAVE_GETPASS +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif /* HAVE_PWD_H */ +#else /* ! HAVE_GETPASS */ +#ifndef __WIN__ +#include <sys/ioctl.h> +#ifdef HAVE_TERMIOS_H /* For tty-password */ +#include <termios.h> +#define TERMIO struct termios +#else +#ifdef HAVE_TERMIO_H /* For tty-password */ +#include <termio.h> +#define TERMIO struct termio +#else +#include <sgtty.h> +#define TERMIO struct sgttyb +#endif +#endif +#ifdef alpha_linux_port +#include <asm/ioctls.h> /* QQ; Fix this in configure */ +#include <asm/termiobits.h> +#endif +#else +#include <conio.h> +#endif /* __WIN__ */ +#endif /* HAVE_GETPASS */ + +#ifdef HAVE_GETPASSPHRASE /* For Solaris */ +#define getpass(A) getpassphrase(A) +#endif + +#ifdef __WIN__ +/* were just going to fake it here and get input from + the keyboard */ + +char *get_tty_password(const char *opt_message) +{ + char to[80]; + char *pos=to,*end=to+sizeof(to)-1; + int i=0; + DBUG_ENTER("get_tty_password"); + _cputs(opt_message ? opt_message : "Enter password: "); + for (;;) + { + char tmp; + tmp=_getch(); + if (tmp == '\b' || (int) tmp == 127) + { + if (pos != to) + { + _cputs("\b \b"); + pos--; + continue; + } + } + if (tmp == '\n' || tmp == '\r' || tmp == 3) + break; + if (iscntrl(tmp) || pos == end) + continue; + _cputs("*"); + *(pos++) = tmp; + } + while (pos != to && isspace(pos[-1]) == ' ') + pos--; /* Allow dummy space at end */ + *pos=0; + _cputs("\n"); + DBUG_RETURN(my_strdup(to,MYF(MY_FAE))); +} + +#else + + +#ifndef HAVE_GETPASS +/* +** Can't use fgets, because readline will get confused +** length is max number of chars in to, not counting \0 +* to will not include the eol characters. +*/ + +static void get_password(char *to,uint length,int fd, my_bool echo) +{ + char *pos=to,*end=to+length; + + for (;;) + { + uchar tmp; + if (my_read(fd,&tmp,1,MYF(0)) != 1) + break; + if (tmp == '\b' || (int) tmp == 127) + { + if (pos != to) + { + if (echo) + { + fputs("\b \b",stderr); + fflush(stderr); + } + pos--; + continue; + } + } + if (tmp == '\n' || tmp == '\r' || tmp == 3) + break; + if (iscntrl(tmp) || pos == end) + continue; + if (echo) + { + fputc('*',stderr); + fflush(stderr); + } + *(pos++)= (char) tmp; + } + while (pos != to && isspace(pos[-1]) == ' ') + pos--; /* Allow dummy space at end */ + *pos=0; + return; +} + +#endif /* ! HAVE_GETPASS */ + + +char *get_tty_password(const char *opt_message) +{ +#ifdef HAVE_GETPASS + char *passbuff; +#else /* ! HAVE_GETPASS */ + TERMIO org,tmp; +#endif /* HAVE_GETPASS */ + char buff[80]; + + DBUG_ENTER("get_tty_password"); + +#ifdef HAVE_GETPASS + passbuff = getpass(opt_message ? opt_message : "Enter password: "); + + /* copy the password to buff and clear original (static) buffer */ + strnmov(buff, passbuff, sizeof(buff) - 1); +#ifdef _PASSWORD_LEN + memset(passbuff, 0, _PASSWORD_LEN); +#endif +#else + if (isatty(fileno(stderr))) + { + fputs(opt_message ? opt_message : "Enter password: ",stderr); + fflush(stderr); + } +#if defined(HAVE_TERMIOS_H) + tcgetattr(fileno(stdin), &org); + tmp = org; + tmp.c_lflag &= ~(ECHO | ISIG | ICANON); + tmp.c_cc[VMIN] = 1; + tmp.c_cc[VTIME] = 0; + tcsetattr(fileno(stdin), TCSADRAIN, &tmp); + get_password(buff, sizeof(buff)-1, fileno(stdin), isatty(fileno(stderr))); + tcsetattr(fileno(stdin), TCSADRAIN, &org); +#elif defined(HAVE_TERMIO_H) + ioctl(fileno(stdin), (int) TCGETA, &org); + tmp=org; + tmp.c_lflag &= ~(ECHO | ISIG | ICANON); + tmp.c_cc[VMIN] = 1; + tmp.c_cc[VTIME]= 0; + ioctl(fileno(stdin),(int) TCSETA, &tmp); + get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr))); + ioctl(fileno(stdin),(int) TCSETA, &org); +#else + gtty(fileno(stdin), &org); + tmp=org; + tmp.sg_flags &= ~ECHO; + tmp.sg_flags |= RAW; + stty(fileno(stdin), &tmp); + get_password(buff,sizeof(buff)-1,fileno(stdin),isatty(fileno(stderr))); + stty(fileno(stdin), &org); +#endif + if (isatty(fileno(stderr))) + fputc('\n',stderr); +#endif /* HAVE_GETPASS */ + + DBUG_RETURN(my_strdup(buff,MYF(MY_FAE))); +} + +#endif /*__WIN__*/ diff --git a/mysys/hash.c b/mysys/hash.c index 50a1d0a54f8..1270d14c1f6 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -23,14 +23,15 @@ #include <m_ctype.h> #include "hash.h" -#define NO_RECORD ((uint) -1) +#define NO_RECORD ~((my_hash_value_type) 0) #define LOWFIND 1 #define LOWUSED 2 #define HIGHFIND 4 #define HIGHUSED 8 typedef struct st_hash_info { - uint next; /* index to next key */ + uint32 next; /* index to next key */ + my_hash_value_type hash_nr; uchar *data; /* data for current entry */ } HASH_LINK; @@ -83,7 +84,7 @@ my_hash_init2(HASH *hash, uint growth_size, CHARSET_INFO *charset, { my_bool res; DBUG_ENTER("my_hash_init"); - DBUG_PRINT("enter",("hash: 0x%lx size: %u", (long) hash, (uint) size)); + DBUG_PRINT("enter",("hash:%p size: %u", hash, (uint) size)); hash->records=0; hash->key_offset=key_offset; @@ -115,17 +116,23 @@ my_hash_init2(HASH *hash, uint growth_size, CHARSET_INFO *charset, static inline void my_hash_free_elements(HASH *hash) { uint records= hash->records; + if (records == 0) + return; + /* Set records to 0 early to guard against anyone looking at the structure during the free process */ hash->records= 0; + if (hash->free) { HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); HASH_LINK *end= data + records; - while (data < end) + do + { (*hash->free)((data++)->data); + } while (data < end); } } @@ -143,8 +150,8 @@ static inline void my_hash_free_elements(HASH *hash) void my_hash_free(HASH *hash) { DBUG_ENTER("my_hash_free"); - DBUG_PRINT("enter",("hash: 0x%lx elements: %ld", - (long) hash, hash->records)); + DBUG_PRINT("enter",("hash:%p elements: %ld", + hash, hash->records)); my_hash_free_elements(hash); hash->free= 0; @@ -165,7 +172,7 @@ void my_hash_free(HASH *hash) void my_hash_reset(HASH *hash) { DBUG_ENTER("my_hash_reset"); - DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash)); + DBUG_PRINT("enter",("hash:%p", hash)); my_hash_free_elements(hash); reset_dynamic(&hash->array); @@ -201,13 +208,10 @@ static uint my_hash_mask(my_hash_value_type hashnr, size_t buffmax, return (uint) (hashnr & ((buffmax >> 1) -1)); } -static uint my_hash_rec_mask(const HASH *hash, HASH_LINK *pos, - size_t buffmax, size_t maxlength) +static inline uint my_hash_rec_mask(HASH_LINK *pos, + size_t buffmax, size_t maxlength) { - size_t length; - uchar *key= (uchar*) my_hash_key(hash, pos->data, &length, 0); - return my_hash_mask(hash->hash_function(hash->charset, key, length), buffmax, - maxlength); + return my_hash_mask(pos->hash_nr, buffmax, maxlength); } @@ -253,13 +257,13 @@ uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length, HASH_SEARCH_STATE *current_record) { uchar *res; - if (my_hash_inited(hash)) - res= my_hash_first_from_hash_value(hash, - hash->hash_function(hash->charset, key, - length ? length : hash->key_length), - key, length, current_record); - else - res= 0; + DBUG_ASSERT(my_hash_inited(hash)); + + res= my_hash_first_from_hash_value(hash, + hash->hash_function(hash->charset, key, + length ? length : + hash->key_length), + key, length, current_record); return res; } @@ -271,14 +275,13 @@ uchar* my_hash_first_from_hash_value(const HASH *hash, HASH_SEARCH_STATE *current_record) { HASH_LINK *pos; - uint flag,idx; DBUG_ENTER("my_hash_first_from_hash_value"); - flag=1; if (hash->records) { - idx= my_hash_mask(hash_value, - hash->blength, hash->records); + uint flag= 1; + uint idx= my_hash_mask(hash_value, + hash->blength, hash->records); do { pos= dynamic_element(&hash->array,idx,HASH_LINK*); @@ -291,7 +294,7 @@ uchar* my_hash_first_from_hash_value(const HASH *hash, if (flag) { flag=0; /* Reset flag */ - if (my_hash_rec_mask(hash, pos, hash->blength, hash->records) != idx) + if (my_hash_rec_mask(pos, hash->blength, hash->records) != idx) break; /* Wrong link */ } } @@ -383,15 +386,19 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, my_bool my_hash_insert(HASH *info, const uchar *record) { int flag; - size_t idx,halfbuff,first_index; - my_hash_value_type hash_nr; - uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); + uint idx, halfbuff, first_index; + size_t length; + my_hash_value_type current_hash_nr, UNINIT_VAR(rec_hash_nr), + UNINIT_VAR(rec2_hash_nr); + uchar *UNINIT_VAR(rec_data),*UNINIT_VAR(rec2_data), *key; HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; + key= (uchar*) my_hash_key(info, record, &length, 1); + current_hash_nr= info->hash_function(info->charset, key, length); + if (info->flags & HASH_UNIQUE) { - uchar *key= (uchar*) my_hash_key(info, record, &idx, 1); - if (my_hash_search(info, key, idx)) + if (my_hash_search_using_hash_value(info, current_hash_nr, key, length)) return(TRUE); /* Duplicate entry */ } @@ -407,8 +414,9 @@ my_bool my_hash_insert(HASH *info, const uchar *record) { do { + my_hash_value_type hash_nr; pos=data+idx; - hash_nr=rec_hashnr(info,pos->data); + hash_nr= pos->hash_nr; if (flag == 0) /* First loop; Check if ok */ if (my_hash_mask(hash_nr, info->blength, info->records) != first_index) break; @@ -418,17 +426,19 @@ my_bool my_hash_insert(HASH *info, const uchar *record) { if (flag & HIGHFIND) { - flag=LOWFIND | HIGHFIND; + flag= LOWFIND | HIGHFIND; /* key shall be moved to the current empty position */ - gpos=empty; - ptr_to_rec=pos->data; + gpos= empty; + rec_data= pos->data; + rec_hash_nr= pos->hash_nr; empty=pos; /* This place is now free */ } else { - flag=LOWFIND | LOWUSED; /* key isn't changed */ - gpos=pos; - ptr_to_rec=pos->data; + flag= LOWFIND | LOWUSED; /* key isn't changed */ + gpos= pos; + rec_data= pos->data; + rec_hash_nr= pos->hash_nr; } } else @@ -436,12 +446,14 @@ my_bool my_hash_insert(HASH *info, const uchar *record) if (!(flag & LOWUSED)) { /* Change link of previous LOW-key */ - gpos->data=ptr_to_rec; - gpos->next= (uint) (pos-data); + gpos->data= rec_data; + gpos->hash_nr= rec_hash_nr; + gpos->next= (uint) (pos-data); flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED); } - gpos=pos; - ptr_to_rec=pos->data; + gpos= pos; + rec_data= pos->data; + rec_hash_nr= pos->hash_nr; } } else @@ -450,20 +462,24 @@ my_bool my_hash_insert(HASH *info, const uchar *record) { flag= (flag & LOWFIND) | HIGHFIND; /* key shall be moved to the last (empty) position */ - gpos2 = empty; empty=pos; - ptr_to_rec2=pos->data; + gpos2= empty; + empty= pos; + rec2_data= pos->data; + rec2_hash_nr= pos->hash_nr; } else { if (!(flag & HIGHUSED)) { /* Change link of previous hash-key and save */ - gpos2->data=ptr_to_rec2; - gpos2->next=(uint) (pos-data); + gpos2->data= rec2_data; + gpos2->hash_nr= rec2_hash_nr; + gpos2->next= (uint) (pos-data); flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED); } - gpos2=pos; - ptr_to_rec2=pos->data; + gpos2= pos; + rec2_data= pos->data; + rec2_hash_nr= pos->hash_nr; } } } @@ -471,41 +487,44 @@ my_bool my_hash_insert(HASH *info, const uchar *record) if ((flag & (LOWFIND | LOWUSED)) == LOWFIND) { - gpos->data=ptr_to_rec; - gpos->next=NO_RECORD; + gpos->data= rec_data; + gpos->hash_nr= rec_hash_nr; + gpos->next= NO_RECORD; } if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND) { - gpos2->data=ptr_to_rec2; - gpos2->next=NO_RECORD; + gpos2->data= rec2_data; + gpos2->hash_nr= rec2_hash_nr; + gpos2->next= NO_RECORD; } } - /* Check if we are at the empty position */ - idx= my_hash_mask(rec_hashnr(info, record), info->blength, info->records + 1); - pos=data+idx; + idx= my_hash_mask(current_hash_nr, info->blength, info->records + 1); + pos= data+idx; + /* Check if we are at the empty position */ if (pos == empty) { - pos->data=(uchar*) record; pos->next=NO_RECORD; } else { - /* Check if more records in same hash-nr family */ - empty[0]=pos[0]; - gpos= data + my_hash_rec_mask(info, pos, info->blength, info->records + 1); + /* Move conflicting record to empty position (last) */ + empty[0]= pos[0]; + /* Check if the moved record was in same hash-nr family */ + gpos= data + my_hash_rec_mask(pos, info->blength, info->records + 1); if (pos == gpos) { - pos->data=(uchar*) record; - pos->next=(uint) (empty - data); + /* Point to moved record */ + pos->next= (uint32) (empty - data); } else { - pos->data=(uchar*) record; - pos->next=NO_RECORD; + pos->next= NO_RECORD; movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data)); } } + pos->data= (uchar*) record; + pos->hash_nr= current_hash_nr; if (++info->records == info->blength) info->blength+= info->blength; return(0); @@ -565,15 +584,14 @@ my_bool my_hash_delete(HASH *hash, uchar *record) else if (pos->next != NO_RECORD) { empty=data+(empty_index=pos->next); - pos->data=empty->data; - pos->next=empty->next; + pos[0]= empty[0]; } - if (empty == lastpos) /* last key at wrong pos or no next link */ + if (empty == lastpos) /* last key at wrong pos or no next link */ goto exit; /* Move the last key (lastpos) */ - lastpos_hashnr=rec_hashnr(hash,lastpos->data); + lastpos_hashnr= lastpos->hash_nr; /* pos is where lastpos should be */ pos= data + my_hash_mask(lastpos_hashnr, hash->blength, hash->records); if (pos == empty) /* Move to empty position. */ @@ -581,7 +599,7 @@ my_bool my_hash_delete(HASH *hash, uchar *record) empty[0]=lastpos[0]; goto exit; } - pos_hashnr=rec_hashnr(hash,pos->data); + pos_hashnr= pos->hash_nr; /* pos3 is where the pos should be */ pos3= data + my_hash_mask(pos_hashnr, hash->blength, hash->records); if (pos != pos3) @@ -624,23 +642,30 @@ exit: my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, size_t old_key_length) { - uint new_index,new_pos_index,records; - size_t idx, empty, blength; + uint new_index, new_pos_index, org_index, records, idx; + size_t length, empty, blength; + my_hash_value_type hash_nr; HASH_LINK org_link,*data,*previous,*pos; + uchar *new_key; DBUG_ENTER("my_hash_update"); + + new_key= (uchar*) my_hash_key(hash, record, &length, 1); + hash_nr= hash->hash_function(hash->charset, new_key, length); if (HASH_UNIQUE & hash->flags) { HASH_SEARCH_STATE state; - uchar *found, *new_key= (uchar*) my_hash_key(hash, record, &idx, 1); - if ((found= my_hash_first(hash, new_key, idx, &state))) + uchar *found; + + if ((found= my_hash_first_from_hash_value(hash, hash_nr, new_key, length, + &state))) { do { if (found != record) DBUG_RETURN(1); /* Duplicate entry */ } - while ((found= my_hash_next(hash, new_key, idx, &state))); + while ((found= my_hash_next(hash, new_key, length, &state))); } } @@ -653,19 +678,24 @@ my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, (old_key_length ? old_key_length : hash->key_length)), blength, records); - new_index= my_hash_mask(rec_hashnr(hash, record), blength, records); - if (idx == new_index) - DBUG_RETURN(0); /* Nothing to do (No record check) */ + org_index= idx; + new_index= my_hash_mask(hash_nr, blength, records); previous=0; for (;;) { - if ((pos= data+idx)->data == record) break; previous=pos; if ((idx=pos->next) == NO_RECORD) DBUG_RETURN(1); /* Not found in links */ } + + if (org_index == new_index) + { + data[idx].hash_nr= hash_nr; /* Hash number may have changed */ + DBUG_RETURN(0); /* Record is in right position */ + } + org_link= *pos; empty=idx; @@ -700,28 +730,31 @@ my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, data[empty]= org_link; } data[empty].next= NO_RECORD; + data[empty].hash_nr= hash_nr; DBUG_RETURN(0); } pos=data+new_index; - new_pos_index= my_hash_rec_mask(hash, pos, blength, records); + new_pos_index= my_hash_rec_mask(pos, blength, records); if (new_index != new_pos_index) { /* Other record in wrong position */ - data[empty] = *pos; + data[empty]= *pos; movelink(data,new_index,new_pos_index, (uint) empty); org_link.next=NO_RECORD; data[new_index]= org_link; + data[new_index].hash_nr= hash_nr; } else { /* Link in chain at right position */ org_link.next=data[new_index].next; data[empty]=org_link; + data[empty].hash_nr= hash_nr; data[new_index].next= (uint) empty; } DBUG_RETURN(0); } -uchar *my_hash_element(HASH *hash, ulong idx) +uchar *my_hash_element(HASH *hash, size_t idx) { if (idx < hash->records) return dynamic_element(&hash->array,idx,HASH_LINK*)->data; @@ -773,7 +806,7 @@ my_bool my_hash_iterate(HASH *hash, my_hash_walk_action action, void *argument) } -#ifndef DBUG_OFF +#if !defined(DBUG_OFF) || defined(MAIN) my_bool my_hash_check(HASH *hash) { @@ -789,7 +822,15 @@ my_bool my_hash_check(HASH *hash) for (i=found=max_links=seek=0 ; i < records ; i++) { - if (my_hash_rec_mask(hash, data + i, blength, records) == i) + size_t length; + uchar *key= (uchar*) my_hash_key(hash, data[i].data, &length, 0); + if (data[i].hash_nr != hash->hash_function(hash->charset, key, length)) + { + DBUG_PRINT("error", ("record at %d has wrong hash", i)); + error= 1; + } + + if (my_hash_rec_mask(data + i, blength, records) == i) { found++; seek++; links=1; for (idx=data[i].next ; @@ -805,12 +846,12 @@ my_bool my_hash_check(HASH *hash) } hash_info=data+idx; seek+= ++links; - if ((rec_link= my_hash_rec_mask(hash, hash_info, + if ((rec_link= my_hash_rec_mask(hash_info, blength, records)) != i) { DBUG_PRINT("error", ("Record in wrong link at %d: Start %d " - "Record: 0x%lx Record-link %d", - idx, i, (long) hash_info->data, rec_link)); + "Record:%p Record-link %d", + idx, i, hash_info->data, rec_link)); error=1; } else @@ -828,6 +869,71 @@ my_bool my_hash_check(HASH *hash) DBUG_PRINT("info", ("records: %u seeks: %d max links: %d hitrate: %.2f", records,seek,max_links,(float) seek / (float) records)); + DBUG_ASSERT(error == 0); return error; } #endif + +#ifdef MAIN + +#define RECORDS 1000 + +uchar *test_get_key(uchar *data, size_t *length, + my_bool not_used __attribute__((unused))) +{ + *length= 2; + return data; +} + + +int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) +{ + uchar records[RECORDS][2], copy[2]; + HASH hash_test; + uint i; + MY_INIT(argv[0]); + DBUG_PUSH("d:t:O,/tmp/test_hash.trace"); + + printf("my_hash_init\n"); + if (my_hash_init2(&hash_test, 100, &my_charset_bin, 20, + 0, 0, (my_hash_get_key) test_get_key, 0, 0, HASH_UNIQUE)) + { + fprintf(stderr, "hash init failed\n"); + exit(1); + } + + printf("my_hash_insert\n"); + for (i= 0 ; i < RECORDS ; i++) + { + int2store(records[i],i); + my_hash_insert(&hash_test, records[i]); + my_hash_check(&hash_test); + } + printf("my_hash_update\n"); + for (i= 0 ; i < RECORDS ; i+=2) + { + memcpy(copy, records[i], 2); + int2store(records[i],i + RECORDS); + if (my_hash_update(&hash_test, records[i], copy, 2)) + { + fprintf(stderr, "hash update failed\n"); + exit(1); + } + my_hash_check(&hash_test); + } + printf("my_hash_delete\n"); + for (i= 0 ; i < RECORDS ; i++) + { + if (my_hash_delete(&hash_test, records[i])) + { + fprintf(stderr, "hash delete failed\n"); + exit(1); + } + my_hash_check(&hash_test); + } + my_hash_free(&hash_test); + printf("ok\n"); + my_end(MY_CHECK_ERROR); + return(0); +} +#endif /* MAIN */ diff --git a/mysys/lf_alloc-pin.c b/mysys/lf_alloc-pin.c index c7777cc8f54..0dc524be336 100644 --- a/mysys/lf_alloc-pin.c +++ b/mysys/lf_alloc-pin.c @@ -121,7 +121,6 @@ void lf_pinbox_init(LF_PINBOX *pinbox, uint free_ptr_offset, lf_pinbox_free_func *free_func, void *free_func_arg) { DBUG_ASSERT(free_ptr_offset % sizeof(void *) == 0); - compile_time_assert(sizeof(LF_PINS) == 128); lf_dynarray_init(&pinbox->pinarray, sizeof(LF_PINS)); pinbox->pinstack_top_ver= 0; pinbox->pins_in_array= 0; @@ -356,7 +355,7 @@ static void lf_pinbox_real_free(LF_PINS *pins) lf_dynarray_iterate(&pinbox->pinarray, (lf_dynarray_func)harvest_pins, &hv); - npins= hv.granary-addr; + npins= (int)(hv.granary-addr); /* and sort them */ if (npins) qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c index c0e7917055b..0dd0c1a94c6 100644 --- a/mysys/lf_hash.c +++ b/mysys/lf_hash.c @@ -308,7 +308,7 @@ static inline const uchar* hash_key(const LF_HASH *hash, @note, that the hash value is limited to 2^31, because we need one bit to distinguish between normal and dummy nodes. */ -static inline my_hash_value_type calc_hash(const CHARSET_INFO *cs, +static inline my_hash_value_type calc_hash(CHARSET_INFO *cs, const uchar *key, size_t keylen) { diff --git a/mysys/list.c b/mysys/list.c index 380de83c031..65da5d452cc 100644 --- a/mysys/list.c +++ b/mysys/list.c @@ -27,7 +27,7 @@ LIST *list_add(LIST *root, LIST *element) { DBUG_ENTER("list_add"); - DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", (long) root, (long) element)); + DBUG_PRINT("enter",("root: %p element: %p", root, element)); if (root) { if (root->prev) /* If add in mid of list */ diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index 53edfc5d87b..fb163899a76 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011, 2013, Monty Program Ab +/* Copyright (c) 2011, 2017, MariaDB Corporation. Copyright (c) 2011, 2012, Oleksandr Byelkin Redistribution and use in source and binary forms, with or without @@ -74,15 +74,15 @@ uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs, 2 bits which determinate size of offset in the header -1 */ /* mask to get above bits */ -#define DYNCOL_FLG_OFFSET (1|2) -#define DYNCOL_FLG_NAMES 4 -#define DYNCOL_FLG_NMOFFSET (8|16) +#define DYNCOL_FLG_OFFSET (1U|2U) +#define DYNCOL_FLG_NAMES 4U +#define DYNCOL_FLG_NMOFFSET (8U|16U) /** All known flags mask that could be set. @note DYNCOL_FLG_NMOFFSET should be 0 for now. */ -#define DYNCOL_FLG_KNOWN (1|2|4) +#define DYNCOL_FLG_KNOWN (1U|2U|4U) /* formats */ enum enum_dyncol_format @@ -294,7 +294,7 @@ static void set_fixed_header_named(DYNAMIC_COLUMN *str, DYN_HEADER *hdr) DBUG_ASSERT(hdr->offset_size <= MAX_OFFSET_LENGTH_NM); /* size of data offset, named format flag, size of names offset (0 means 2) */ str->str[0]= - (char) ((str->str[0] & ~(DYNCOL_FLG_OFFSET | DYNCOL_FLG_NMOFFSET)) | + (char) (((uchar)str->str[0] & ~(DYNCOL_FLG_OFFSET | DYNCOL_FLG_NMOFFSET)) | (hdr->offset_size - 2) | DYNCOL_FLG_NAMES); int2store(str->str + 1, hdr->column_count); /* columns number */ int2store(str->str + 3, hdr->nmpool_size); @@ -319,7 +319,7 @@ static my_bool type_and_offset_store_num(uchar *place, size_t offset_size, { ulong val = (((ulong) offset) << 3) | (type - 1); DBUG_ASSERT(type != DYN_COL_NULL); - DBUG_ASSERT(((type - 1) & (~7)) == 0); /* fit in 3 bits */ + DBUG_ASSERT(((type - 1) & (~7U)) == 0); /* fit in 3 bits */ DBUG_ASSERT(offset_size >= 1 && offset_size <= 4); /* Index entry starts with column number; jump over it */ @@ -359,7 +359,7 @@ static my_bool type_and_offset_store_named(uchar *place, size_t offset_size, { ulonglong val = (((ulong) offset) << 4) | (type - 1); DBUG_ASSERT(type != DYN_COL_NULL); - DBUG_ASSERT(((type - 1) & (~0xf)) == 0); /* fit in 4 bits */ + DBUG_ASSERT(((type - 1) & (~0xfU)) == 0); /* fit in 4 bits */ DBUG_ASSERT(offset_size >= 2 && offset_size <= 5); /* Index entry starts with name offset; jump over it */ @@ -566,7 +566,7 @@ static my_bool type_and_offset_read_named(DYNAMIC_COLUMN_TYPE *type, return 1; } *type= (val & 0xf) + 1; - *offset= val >> 4; + *offset= (size_t) (val >> 4); return (*offset >= lim); } @@ -2803,7 +2803,7 @@ dynamic_column_update_copy(DYNAMIC_COLUMN *str, PLAN *plan, else if (offs < first_offset) goto err; - offs+= plan[i].ddelta; + offs+= (size_t) plan[i].ddelta; { DYNAMIC_COLUMN_VALUE val; val.type= tp; // only the type used in the header @@ -2969,7 +2969,7 @@ dynamic_column_update_move_left(DYNAMIC_COLUMN *str, PLAN *plan, return ER_DYNCOL_FORMAT; } - offs+= plan[i].ddelta; + offs+= (size_t) plan[i].ddelta; int2store(write, nm); /* write rest of data at write + COLUMN_NUMBER_SIZE */ type_and_offset_store_num(write, new_offset_size, tp, offs); @@ -3023,9 +3023,9 @@ dynamic_column_update_move_left(DYNAMIC_COLUMN *str, PLAN *plan, memmove((header_base + new_header_size + plan[i].mv_offset + plan[i].ddelta), header_base + header_size + plan[i].mv_offset, - plan[i].mv_length); + (size_t) plan[i].mv_length); } - str->length+= plan[i].mv_length; + str->length+= (size_t) plan[i].mv_length; /* new data adding */ if (i < add_column_count) @@ -3514,8 +3514,8 @@ dynamic_column_update_many_fmt(DYNAMIC_COLUMN *str, Check if it is only "increasing" or only "decreasing" plan for (header and data separately). */ - new_header.data_size= header.data_size + data_delta; - new_header.nmpool_size= new_header.nmpool_size + name_delta; + new_header.data_size= (size_t) (header.data_size + data_delta); + new_header.nmpool_size= (size_t) (new_header.nmpool_size + name_delta); DBUG_ASSERT(new_header.format != dyncol_fmt_num || new_header.nmpool_size == 0); if ((new_header.offset_size= diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 1245a622262..d7689e204b6 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -74,34 +74,6 @@ int (*_my_b_encr_read)(IO_CACHE *info,uchar *Buffer,size_t Count)= 0; int (*_my_b_encr_write)(IO_CACHE *info,const uchar *Buffer,size_t Count)= 0; -/* - Setup internal pointers inside IO_CACHE - - SYNOPSIS - setup_io_cache() - info IO_CACHE handler - - NOTES - This is called on automatically on init or reinit of IO_CACHE - It must be called externally if one moves or copies an IO_CACHE - object. -*/ - -void setup_io_cache(IO_CACHE* info) -{ - /* Ensure that my_b_tell() and my_b_bytes_in_cache works */ - if (info->type == WRITE_CACHE) - { - info->current_pos= &info->write_pos; - info->current_end= &info->write_end; - } - else - { - info->current_pos= &info->read_pos; - info->current_end= &info->read_end; - } -} - static void init_functions(IO_CACHE* info) @@ -148,8 +120,10 @@ init_functions(IO_CACHE* info) DBUG_ASSERT(0); break; } - - setup_io_cache(info); + if (type == READ_CACHE || type == WRITE_CACHE || type == SEQ_READ_APPEND) + info->myflags|= MY_FULL_IO; + else + info->myflags&= ~MY_FULL_IO; } @@ -184,8 +158,8 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, my_off_t pos; my_off_t end_of_file= ~(my_off_t) 0; DBUG_ENTER("init_io_cache"); - DBUG_PRINT("enter",("cache: 0x%lx type: %d pos: %ld", - (ulong) info, (int) type, (ulong) seek_offset)); + DBUG_PRINT("enter",("cache:%p type: %d pos: %llu", + info, (int) type, (ulonglong) seek_offset)); info->file= file; info->type= TYPE_NOT_SET; /* Don't set it until mutex are created */ @@ -193,6 +167,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, info->alloced_buffer = 0; info->buffer=0; info->seek_not_done= 0; + info->next_file_user= NULL; if (file >= 0) { @@ -325,13 +300,115 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, } info->inited=info->aio_result.pending=0; #endif - if (type == READ_CACHE || type == WRITE_CACHE || type == SEQ_READ_APPEND) - info->myflags|= MY_FULL_IO; - else - info->myflags&= ~MY_FULL_IO; DBUG_RETURN(0); } /* init_io_cache */ + + +/* + Initialize the slave IO_CACHE to read the same file (and data) + as master does. + + One can create multiple slaves from a single master. Every slave and master + will have independent file positions. + + The master must be a non-shared READ_CACHE. + It is assumed that no more reads are done after a master and/or a slave + has been freed (this limitation can be easily lifted). +*/ + +int init_slave_io_cache(IO_CACHE *master, IO_CACHE *slave) +{ + uchar *slave_buf; + DBUG_ASSERT(master->type == READ_CACHE); + DBUG_ASSERT(!master->share); + DBUG_ASSERT(master->alloced_buffer); + + if (!(slave_buf= (uchar*)my_malloc(master->buffer_length, MYF(0)))) + { + return 1; + } + memcpy(slave, master, sizeof(IO_CACHE)); + slave->buffer= slave_buf; + + memcpy(slave->buffer, master->buffer, master->buffer_length); + slave->read_pos= slave->buffer + (master->read_pos - master->buffer); + slave->read_end= slave->buffer + (master->read_end - master->buffer); + + if (master->next_file_user) + { + IO_CACHE *p; + for (p= master->next_file_user; + p->next_file_user !=master; + p= p->next_file_user) + {} + + p->next_file_user= slave; + slave->next_file_user= master; + } + else + { + slave->next_file_user= master; + master->next_file_user= slave; + } + return 0; +} + + +void end_slave_io_cache(IO_CACHE *cache) +{ + /* Remove the cache from the next_file_user circular linked list. */ + if (cache->next_file_user != cache) + { + IO_CACHE *p= cache->next_file_user; + while (p->next_file_user != cache) + p= p->next_file_user; + p->next_file_user= cache->next_file_user; + + } + my_free(cache->buffer); +} + +/* + Seek a read io cache to a given offset +*/ +void seek_io_cache(IO_CACHE *cache, my_off_t needed_offset) +{ + my_off_t cached_data_start= cache->pos_in_file; + my_off_t cached_data_end= cache->pos_in_file + (cache->read_end - + cache->buffer); + + if (needed_offset >= cached_data_start && + needed_offset < cached_data_end) + { + /* + The offset we're seeking to is in the buffer. + Move buffer's read position accordingly + */ + cache->read_pos= cache->buffer + (needed_offset - cached_data_start); + } + else + { + if (needed_offset > cache->end_of_file) + needed_offset= cache->end_of_file; + /* + The offset we're seeking to is not in the buffer. + - Set the buffer to be exhausted. + - Make the next read to a mysql_file_seek() call to the required + offset. + TODO(cvicentiu, spetrunia) properly implement aligned seeks for + efficiency. + */ + cache->seek_not_done= 1; + cache->pos_in_file= needed_offset; + /* When reading it must appear as if we've started from the offset + that we've seeked here. We must let _my_b_cache_read assume that + by implying "no reading starting from pos_in_file" has happened. */ + cache->read_pos= cache->buffer; + cache->read_end= cache->buffer; + } +} + /* Wait until current request is ready */ #ifdef HAVE_AIOWAIT @@ -373,8 +450,8 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, my_bool clear_cache) { DBUG_ENTER("reinit_io_cache"); - DBUG_PRINT("enter",("cache: 0x%lx type: %d seek_offset: %lu clear_cache: %d", - (ulong) info, type, (ulong) seek_offset, + DBUG_PRINT("enter",("cache:%p type: %d seek_offset: %llu clear_cache: %d", + info, type, (ulonglong) seek_offset, (int) clear_cache)); DBUG_ASSERT(type == READ_CACHE || type == WRITE_CACHE); @@ -521,7 +598,7 @@ int _my_b_write(IO_CACHE *info, const uchar *Buffer, size_t Count) { my_off_t old_pos_in_file= info->pos_in_file; res= info->write_function(info, Buffer, Count); - Count-= info->pos_in_file - old_pos_in_file; + Count-= (size_t) (info->pos_in_file - old_pos_in_file); Buffer+= info->pos_in_file - old_pos_in_file; } else @@ -587,6 +664,17 @@ int _my_b_cache_read(IO_CACHE *info, uchar *Buffer, size_t Count) { /* No error, reset seek_not_done flag. */ info->seek_not_done= 0; + + if (info->next_file_user) + { + IO_CACHE *c; + for (c= info->next_file_user; + c!= info; + c= c->next_file_user) + { + c->seek_not_done= 1; + } + } } else { @@ -678,22 +766,35 @@ int _my_b_cache_read(IO_CACHE *info, uchar *Buffer, size_t Count) length= 0; /* non-zero size read was done */ } } - else if ((length= mysql_file_read(info->file,info->buffer, max_length, + else + { + if (info->next_file_user) + { + IO_CACHE *c; + for (c= info->next_file_user; + c!= info; + c= c->next_file_user) + { + c->seek_not_done= 1; + } + } + if ((length= mysql_file_read(info->file,info->buffer, max_length, info->myflags)) < Count || length == (size_t) -1) - { - /* - We got an read error, or less than requested (end of file). - If not a read error, copy, what we got. - */ - if (length != (size_t) -1) - memcpy(Buffer, info->buffer, length); - info->pos_in_file= pos_in_file; - /* For a read error, return -1, otherwise, what we got in total. */ - info->error= length == (size_t) -1 ? -1 : (int) (length+left_length); - info->read_pos=info->read_end=info->buffer; - info->seek_not_done=1; - DBUG_RETURN(1); + { + /* + We got an read error, or less than requested (end of file). + If not a read error, copy, what we got. + */ + if (length != (size_t) -1) + memcpy(Buffer, info->buffer, length); + info->pos_in_file= pos_in_file; + /* For a read error, return -1, otherwise, what we got in total. */ + info->error= length == (size_t) -1 ? -1 : (int) (length+left_length); + info->read_pos=info->read_end=info->buffer; + info->seek_not_done=1; + DBUG_RETURN(1); + } } /* Count is the remaining number of bytes requested. @@ -780,10 +881,10 @@ void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, IO_CACHE *write_cache, uint num_threads) { DBUG_ENTER("init_io_cache_share"); - DBUG_PRINT("io_cache_share", ("read_cache: 0x%lx share: 0x%lx " - "write_cache: 0x%lx threads: %u", - (long) read_cache, (long) cshare, - (long) write_cache, num_threads)); + DBUG_PRINT("io_cache_share", ("read_cache: %p share: %p " + "write_cache: %p threads: %u", + read_cache, cshare, + write_cache, num_threads)); DBUG_ASSERT(num_threads > 1); DBUG_ASSERT(read_cache->type == READ_CACHE); @@ -804,8 +905,6 @@ void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, read_cache->share= cshare; read_cache->read_function= _my_b_cache_read_r; - read_cache->current_pos= NULL; - read_cache->current_end= NULL; if (write_cache) { @@ -847,9 +946,9 @@ void remove_io_thread(IO_CACHE *cache) flush_io_cache(cache); mysql_mutex_lock(&cshare->mutex); - DBUG_PRINT("io_cache_share", ("%s: 0x%lx", + DBUG_PRINT("io_cache_share", ("%s: %p", (cache == cshare->source_cache) ? - "writer" : "reader", (long) cache)); + "writer" : "reader", cache)); /* Remove from share. */ total= --cshare->total_threads; @@ -923,9 +1022,9 @@ static int lock_io_cache(IO_CACHE *cache, my_off_t pos) /* Enter the lock. */ mysql_mutex_lock(&cshare->mutex); cshare->running_threads--; - DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u", + DBUG_PRINT("io_cache_share", ("%s: %p pos: %lu running: %u", (cache == cshare->source_cache) ? - "writer" : "reader", (long) cache, (ulong) pos, + "writer" : "reader", cache, (ulong) pos, cshare->running_threads)); if (cshare->source_cache) @@ -1062,10 +1161,10 @@ static void unlock_io_cache(IO_CACHE *cache) { IO_CACHE_SHARE *cshare= cache->share; DBUG_ENTER("unlock_io_cache"); - DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u", + DBUG_PRINT("io_cache_share", ("%s: %p pos: %lu running: %u", (cache == cshare->source_cache) ? "writer" : "reader", - (long) cache, (ulong) cshare->pos_in_file, + cache, (ulong) cshare->pos_in_file, cshare->total_threads)); cshare->running_threads= cshare->total_threads; @@ -1236,7 +1335,7 @@ static int _my_b_cache_read_r(IO_CACHE *cache, uchar *Buffer, size_t Count) static void copy_to_read_buffer(IO_CACHE *write_cache, const uchar *write_buffer, my_off_t pos_in_file) { - size_t write_length= write_cache->pos_in_file - pos_in_file; + size_t write_length= (size_t) (write_cache->pos_in_file - pos_in_file); IO_CACHE_SHARE *cshare= write_cache->share; DBUG_ASSERT(cshare->source_cache == write_cache); @@ -1816,7 +1915,7 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock) size_t length; my_bool append_cache= (info->type == SEQ_READ_APPEND); DBUG_ENTER("my_b_flush_io_cache"); - DBUG_PRINT("enter", ("cache: 0x%lx", (long) info)); + DBUG_PRINT("enter", ("cache: %p", info)); if (!append_cache) need_append_buffer_lock= 0; @@ -1894,7 +1993,7 @@ int end_io_cache(IO_CACHE *info) { int error=0; DBUG_ENTER("end_io_cache"); - DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info)); + DBUG_PRINT("enter",("cache: %p", info)); /* Every thread must call remove_io_thread(). The last one destroys diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 299a9390b9b..aab26384be7 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. + Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -274,16 +275,16 @@ struct st_hash_link }; /* simple states of a block */ -#define BLOCK_ERROR 1 /* an error occurred when performing file i/o */ -#define BLOCK_READ 2 /* file block is in the block buffer */ -#define BLOCK_IN_SWITCH 4 /* block is preparing to read new page */ -#define BLOCK_REASSIGNED 8 /* blk does not accept requests for old page */ -#define BLOCK_IN_FLUSH 16 /* block is selected for flush */ -#define BLOCK_CHANGED 32 /* block buffer contains a dirty page */ -#define BLOCK_IN_USE 64 /* block is not free */ -#define BLOCK_IN_EVICTION 128 /* block is selected for eviction */ -#define BLOCK_IN_FLUSHWRITE 256 /* block is in write to file */ -#define BLOCK_FOR_UPDATE 512 /* block is selected for buffer modification */ +#define BLOCK_ERROR 1U/* an error occurred when performing file i/o */ +#define BLOCK_READ 2U/* file block is in the block buffer */ +#define BLOCK_IN_SWITCH 4U/* block is preparing to read new page */ +#define BLOCK_REASSIGNED 8U/* blk does not accept requests for old page */ +#define BLOCK_IN_FLUSH 16U/* block is selected for flush */ +#define BLOCK_CHANGED 32U/* block buffer contains a dirty page */ +#define BLOCK_IN_USE 64U/* block is not free */ +#define BLOCK_IN_EVICTION 128U/* block is selected for eviction */ +#define BLOCK_IN_FLUSHWRITE 256U/* block is in write to file */ +#define BLOCK_FOR_UPDATE 512U/* block is selected for buffer modification */ /* page status, returned by find_key_block */ #define PAGE_READ 0 @@ -608,11 +609,11 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, keycache->waiting_for_hash_link.last_thread= NULL; keycache->waiting_for_block.last_thread= NULL; DBUG_PRINT("exit", - ("disk_blocks: %d block_root: 0x%lx hash_entries: %d\ - hash_root: 0x%lx hash_links: %d hash_link_root: 0x%lx", - keycache->disk_blocks, (long) keycache->block_root, - keycache->hash_entries, (long) keycache->hash_root, - keycache->hash_links, (long) keycache->hash_link_root)); + ("disk_blocks: %d block_root: %p hash_entries: %d\ + hash_root: %p hash_links: %d hash_link_root: %p", + keycache->disk_blocks, keycache->block_root, + keycache->hash_entries, keycache->hash_root, + keycache->hash_links, keycache->hash_link_root)); } else { @@ -962,7 +963,7 @@ static void end_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, my_bool cleanup) { DBUG_ENTER("end_simple_key_cache"); - DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache)); + DBUG_PRINT("enter", ("key_cache: %p", keycache)); if (!keycache->key_cache_inited) DBUG_VOID_RETURN; @@ -1068,7 +1069,7 @@ static void link_into_queue(KEYCACHE_WQUEUE *wqueue, static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, struct st_my_thread_var *thread) { - KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", (ulong) thread->id)); DBUG_ASSERT(thread->next && thread->prev); if (thread->next == thread) @@ -1145,7 +1146,7 @@ static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, */ do { - KEYCACHE_DBUG_PRINT("wait", ("suspend thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("wait", ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, mutex); } while (thread->next); @@ -1184,7 +1185,7 @@ static void release_whole_queue(KEYCACHE_WQUEUE *wqueue) thread=next; DBUG_ASSERT(thread && thread->init == 1); KEYCACHE_DBUG_PRINT("release_whole_queue: signal", - ("thread %ld", thread->id)); + ("thread %ld", (ulong) thread->id)); /* Take thread from queue. */ next= thread->next; thread->next= NULL; @@ -1388,7 +1389,8 @@ static void link_block(SIMPLE_KEY_CACHE_CB *keycache, BLOCK_LINK *block, */ if ((HASH_LINK *) thread->keycache_link == hash_link) { - KEYCACHE_DBUG_PRINT("link_block: signal", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("link_block: signal", + ("thread %ld", (ulong) thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_block, thread); block->requests++; @@ -1677,7 +1679,7 @@ static void wait_for_readers(SIMPLE_KEY_CACHE_CB *keycache, { KEYCACHE_DBUG_PRINT("wait_for_readers: wait", ("suspend thread %ld block %u", - thread->id, BLOCK_NUMBER(block))); + (ulong) thread->id, BLOCK_NUMBER(block))); /* There must be no other waiter. We have no queue here. */ DBUG_ASSERT(!block->condvar); block->condvar= &thread->suspend; @@ -1737,7 +1739,8 @@ static void unlink_hash(SIMPLE_KEY_CACHE_CB *keycache, HASH_LINK *hash_link) */ if (page->file == hash_link->file && page->filepos == hash_link->diskpos) { - KEYCACHE_DBUG_PRINT("unlink_hash: signal", ("thread %ld", thread->id)); + KEYCACHE_DBUG_PRINT("unlink_hash: signal", + ("thread %ld", (ulong) thread->id)); keycache_pthread_cond_signal(&thread->suspend); unlink_from_queue(&keycache->waiting_for_hash_link, thread); } @@ -1821,7 +1824,7 @@ restart: thread->keycache_link= (void *) &page; link_into_queue(&keycache->waiting_for_hash_link, thread); KEYCACHE_DBUG_PRINT("get_hash_link: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); thread->keycache_link= NULL; @@ -1987,7 +1990,7 @@ restart: do { KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } while (thread->next); @@ -2334,7 +2337,7 @@ restart: do { KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); + ("suspend thread %ld", (ulong) thread->id)); keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); } @@ -4363,7 +4366,7 @@ int flush_simple_key_cache_blocks(SIMPLE_KEY_CACHE_CB *keycache, { int res= 0; DBUG_ENTER("flush_key_blocks"); - DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache)); + DBUG_PRINT("enter", ("keycache: %p", keycache)); if (!keycache->key_cache_inited) DBUG_RETURN(0); @@ -4585,7 +4588,7 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) KEYCACHE_PAGE *page; uint i; - fprintf(keycache_dump_file, "thread:%u\n", thread->id); + fprintf(keycache_dump_file, "thread:%lu\n", (ulong) thread->id); i=0; thread=last=waiting_for_hash_link.last_thread; @@ -4596,8 +4599,8 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) thread=thread->next; page= (KEYCACHE_PAGE *) thread->keycache_link; fprintf(keycache_dump_file, - "thread:%u, (file,filepos)=(%u,%lu)\n", - thread->id,(uint) page->file,(ulong) page->filepos); + "thread:%lu, (file,filepos)=(%u,%lu)\n", + (ulong) thread->id,(uint) page->file,(ulong) page->filepos); if (++i == MAX_QUEUE_LEN) break; } @@ -4612,8 +4615,8 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) thread=thread->next; hash_link= (HASH_LINK *) thread->keycache_link; fprintf(keycache_dump_file, - "thread:%u hash_link:%u (file,filepos)=(%u,%lu)\n", - thread->id, (uint) HASH_LINK_NUMBER(hash_link), + "thread:%lu hash_link:%u (file,filepos)=(%u,%lu)\n", + (ulong) thread->id, (uint) HASH_LINK_NUMBER(hash_link), (uint) hash_link->file,(ulong) hash_link->diskpos); if (++i == MAX_QUEUE_LEN) break; @@ -4640,7 +4643,7 @@ static void keycache_dump(SIMPLE_KEY_CACHE_CB *keycache) { thread=thread->next; fprintf(keycache_dump_file, - "thread:%u\n", thread->id); + "thread:%lu\n", (ulong) thread->id); if (++i == MAX_QUEUE_LEN) break; } @@ -4792,11 +4795,11 @@ void keycache_debug_log_close(void) static int fail_block(BLOCK_LINK *block) { - F_B_PRT("block->next_used: %lx\n", (ulong) block->next_used); - F_B_PRT("block->prev_used: %lx\n", (ulong) block->prev_used); - F_B_PRT("block->next_changed: %lx\n", (ulong) block->next_changed); - F_B_PRT("block->prev_changed: %lx\n", (ulong) block->prev_changed); - F_B_PRT("block->hash_link: %lx\n", (ulong) block->hash_link); + F_B_PRT("block->next_used: %p\n", block->next_used); + F_B_PRT("block->prev_used: %p\n", block->prev_used); + F_B_PRT("block->next_changed: %p\n", block->next_changed); + F_B_PRT("block->prev_changed: %p\n", block->prev_changed); + F_B_PRT("block->hash_link: %p\n", block->hash_link); F_B_PRT("block->status: %u\n", block->status); F_B_PRT("block->length: %u\n", block->length); F_B_PRT("block->offset: %u\n", block->offset); @@ -4807,9 +4810,9 @@ static int fail_block(BLOCK_LINK *block) static int fail_hlink(HASH_LINK *hlink) { - F_B_PRT("hlink->next: %lx\n", (ulong) hlink->next); - F_B_PRT("hlink->prev: %lx\n", (ulong) hlink->prev); - F_B_PRT("hlink->block: %lx\n", (ulong) hlink->block); + F_B_PRT("hlink->next: %p\n", hlink->next); + F_B_PRT("hlink->prev: %p\n", hlink->prev); + F_B_PRT("hlink->block: %p\n", hlink->block); F_B_PRT("hlink->diskpos: %lu\n", (ulong) hlink->diskpos); F_B_PRT("hlink->file: %d\n", hlink->file); return 0; /* Let the assert fail. */ @@ -5187,7 +5190,7 @@ int init_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache, } } - keycache->partitions= partitions= partition_ptr-keycache->partition_array; + keycache->partitions= partitions= (uint) (partition_ptr-keycache->partition_array); keycache->key_cache_mem_size= mem_per_cache * partitions; for (i= 0; i < (int) partitions; i++) keycache->partition_array[i]->hash_factor= partitions; @@ -5355,7 +5358,7 @@ void end_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache, uint i; uint partitions= keycache->partitions; DBUG_ENTER("partitioned_end_key_cache"); - DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache)); + DBUG_PRINT("enter", ("key_cache: %p", keycache)); for (i= 0; i < partitions; i++) { @@ -5669,7 +5672,7 @@ int flush_partitioned_key_cache_blocks(PARTITIONED_KEY_CACHE_CB *keycache, int err= 0; ulonglong *dirty_part_map= (ulonglong *) file_extra; DBUG_ENTER("partitioned_flush_key_blocks"); - DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache)); + DBUG_PRINT("enter", ("keycache: %p", keycache)); for (i= 0; i < partitions; i++) { diff --git a/mysys/mulalloc.c b/mysys/mulalloc.c index f22464e45ee..26f8253bc87 100644 --- a/mysys/mulalloc.c +++ b/mysys/mulalloc.c @@ -80,7 +80,7 @@ void *my_multi_malloc_large(myf myFlags, ...) { va_list args; char **ptr,*start,*res; - size_t tot_length,length; + ulonglong tot_length,length; DBUG_ENTER("my_multi_malloc"); va_start(args,myFlags); @@ -92,7 +92,7 @@ void *my_multi_malloc_large(myf myFlags, ...) } va_end(args); - if (!(start=(char *) my_malloc(tot_length, myFlags))) + if (!(start=(char *) my_malloc((size_t) tot_length, myFlags))) DBUG_RETURN(0); /* purecov: inspected */ va_start(args,myFlags); diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index ecb512572b1..3f20f535d37 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -49,6 +49,13 @@ static const char *strip_path(const char *s) static bfd *bfdh= 0; static asymbol **symtable= 0; +#if defined(HAVE_LINK_H) && defined(HAVE_DLOPEN) +#include <link.h> +static ElfW(Addr) offset= 0; +#else +#define offset 0 +#endif + #ifndef bfd_get_section_flags #define bfd_get_section_flags(H, S) bfd_section_flags(S) #endif /* bfd_get_section_flags */ @@ -72,7 +79,7 @@ static asymbol **symtable= 0; */ int my_addr_resolve(void *ptr, my_addr_loc *loc) { - bfd_vma addr= (intptr)ptr; + bfd_vma addr= (intptr)ptr - offset; asection *sec; for (sec= bfdh->sections; sec; sec= sec->next) @@ -115,6 +122,12 @@ const char *my_addr_resolve_init() uint unused; char **matching; +#if defined(HAVE_LINK_H) && defined(HAVE_DLOPEN) + struct link_map *lm = (struct link_map*) dlopen(0, RTLD_NOW); + if (lm) + offset= lm->l_addr; +#endif + bfdh= bfd_openr(my_progname, NULL); if (!bfdh) goto err; @@ -144,7 +157,6 @@ err: #include <m_string.h> #include <ctype.h> - #include <sys/wait.h> static int in[2], out[2]; @@ -220,7 +232,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) if (start_addr2line_fork(info.dli_fname)) { addr2line_binary[0] = '\0'; - return 1; + return 2; } /* Save result for future comparisons. */ strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); @@ -228,7 +240,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) offset = info.dli_fbase; len= my_snprintf(input, sizeof(input), "%08x\n", (ulonglong)(ptr - offset)); if (write(in[1], input, len) <= 0) - return 1; + return 3; FD_ZERO(&set); FD_SET(out[0], &set); @@ -243,7 +255,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) extra_bytes_read= read(out[0], output + total_bytes_read, sizeof(output) - total_bytes_read); if (extra_bytes_read < 0) - return 1; + return 4; /* Timeout or max bytes read. */ if (extra_bytes_read == 0) break; @@ -271,7 +283,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) /* Response is malformed. */ if (filename_start == -1 || line_number_start == -1) - return 1; + return 5; loc->func= output; loc->file= output + filename_start; @@ -279,7 +291,7 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) /* Addr2line was unable to extract any meaningful information. */ if (strcmp(loc->file, "??") == 0) - return 1; + return 6; loc->file= strip_path(loc->file); diff --git a/mysys/my_atomic_writes.c b/mysys/my_atomic_writes.c new file mode 100644 index 00000000000..0b54a207713 --- /dev/null +++ b/mysys/my_atomic_writes.c @@ -0,0 +1,333 @@ +/* Copyright (c) 2016, MariaDB Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "mysys_priv.h" + +my_bool my_may_have_atomic_write= 0; + +#ifdef __linux__ + +my_bool has_shannon_atomic_write= 0, has_fusion_io_atomic_write= 0; + +#include <sys/ioctl.h> + + +/*********************************************************************** + FUSION_IO +************************************************************************/ + +/** FusionIO atomic write control info */ +#define DFS_IOCTL_ATOMIC_WRITE_SET _IOW(0x95, 2, uint) + + +/** + Check if the system has a funsion_io card + @return TRUE Card exists +*/ + +static my_bool test_if_fusion_io_card_exists() +{ + /* Fusion card requires fallocate to exists */ +#ifndef HAVE_POSIX_FALLOCATE + return 0; +#else + return (access("/dev/fcta", F_OK)) == 0; +#endif +} + + +/** + Check if a file is on a Fusion_IO device and that it supports atomic_write + @param[in] file OS file handle + @param[in] page_size page size + @return TRUE Atomic write supported +*/ + +static my_bool fusion_io_has_atomic_write(File file, int page_size) +{ + int atomic= 1; + if (page_size <= 32768 && + ioctl(file, DFS_IOCTL_ATOMIC_WRITE_SET, &atomic) != -1) + return(TRUE); + return(FALSE); +} + + +/*********************************************************************** + SHANNON +************************************************************************/ + +#define SHANNON_IOMAGIC 'x' +#define SHANNON_IOCQATOMIC_SIZE _IO(SHANNON_IOMAGIC, 22) + +#define SHANNON_MAX_DEVICES 32 +#define SHANNON_NO_ATOMIC_SIZE_YET -2 + +struct shannon_dev +{ + char dev_name[32]; + dev_t st_dev; + int atomic_size; +}; + + +static struct shannon_dev shannon_devices[SHANNON_MAX_DEVICES+1]; + +/** + Check if the system has a Shannon card + If card exists, record device numbers to allow us to later check if + a given file is on this device. + @return TRUE Card exists +*/ + +static my_bool test_if_shannon_card_exists() +{ + uint shannon_found_devices= 0; + char dev_part; + uint dev_no; + + if (access("/dev/scta", F_OK) < 0) + return 0; + + /* + The Shannon devices are /dev/dfX, where X can be from a-z. + We have to check all of them as some may be missing if the user + removed one with the U.2 interface. + */ + + for (dev_part= 'a' ; dev_part < 'z' ; dev_part++) + { + char path[32]; + struct stat stat_buff; + + sprintf(path, "/dev/df%c", dev_part); +#ifdef TEST_SHANNON + if (lstat(path, &stat_buff) < 0) + { + printf("%s(): lstat failed.\n", __func__); + break; + } +#endif + shannon_devices[shannon_found_devices].st_dev= stat_buff.st_rdev; + sprintf(shannon_devices[shannon_found_devices].dev_name, "/dev/sct%c", + dev_part); + +#ifdef TEST_SHANNON + printf("%s(): i=%d, stat_buff.st_dev=0x%lx, stat_buff.st_rdev=0x%lx, st_rdev=0x%lx, dev_name=%s\n", + __func__, + shannon_found_devices, + (ulong) stat_buff.st_dev, + (ulong) stat_buff.st_rdev, + (ulong) shannon_devices[shannon_found_devices].st_dev, + shannon_devices[shannon_found_devices].dev_name); +#endif + + /* + The atomic size will be checked on first access. This is needed + as a normal user can't open the /dev/scta file + */ + shannon_devices[shannon_found_devices].atomic_size= + SHANNON_NO_ATOMIC_SIZE_YET; + if (++shannon_found_devices== SHANNON_MAX_DEVICES) + goto end; + + for (dev_no= 1 ; dev_no < 9 ; dev_no++) + { + sprintf(path, "/dev/df%c%d", dev_part, dev_no); + if (lstat(path, &stat_buff) < 0) + break; + + shannon_devices[shannon_found_devices].st_dev= stat_buff.st_rdev; + sprintf(shannon_devices[shannon_found_devices].dev_name, "/dev/sct%c%d", + dev_part, dev_no); + +#ifdef TEST_SHANNON + printf("%s(): i=%d, st_dev=0x%lx, st_rdev=0x%lx, dev_name=%s\n", + __func__, + shannon_found_devices, + (ulong) stat_buff.st_dev, + (ulong) shannon_devices[shannon_found_devices].st_dev, + shannon_devices[shannon_found_devices].dev_name); +#endif + + /* + The atomic size will be checked on first access. This is needed + as a normal user can't open the /dev/scta file + */ + shannon_devices[shannon_found_devices].atomic_size= + SHANNON_NO_ATOMIC_SIZE_YET; + if (++shannon_found_devices == SHANNON_MAX_DEVICES) + goto end; + } + } +end: + shannon_devices[shannon_found_devices].st_dev= 0; + return shannon_found_devices > 0; +} + + +static my_bool shannon_dev_has_atomic_write(struct shannon_dev *dev, + int page_size) +{ +#ifdef TEST_SHANNON + printf("%s: enter: page_size=%d, atomic_size=%d, dev_name=%s\n", + __func__, + page_size, + dev->atomic_size, + dev->dev_name); +#endif + if (dev->atomic_size == SHANNON_NO_ATOMIC_SIZE_YET) + { + int fd= open(dev->dev_name, 0); + if (fd < 0) + { + perror("open() failed!"); + dev->atomic_size= 0; /* Don't try again */ + return FALSE; + } + dev->atomic_size= ioctl(fd, SHANNON_IOCQATOMIC_SIZE); + close(fd); + } + +#ifdef TEST_SHANNON + printf("%s: exit: page_size=%d, atomic_size=%d, dev_name=%s\n", + __func__, + page_size, + dev->atomic_size, + dev->dev_name); +#endif + return (page_size <= dev->atomic_size); +} + + +/** + Check if a file is on a Shannon device and that it supports atomic_write + @param[in] file OS file handle + @param[in] page_size page size + @return TRUE Atomic write supported + + @notes + This is called only at first open of a file. In this case it's doesn't + matter so much that we loop over all cards. + We update the atomic size on first access. +*/ + +static my_bool shannon_has_atomic_write(File file, int page_size) +{ + struct shannon_dev *dev; + struct stat stat_buff; + + if (fstat(file, &stat_buff) < 0) + { +#ifdef TEST_SHANNON + printf("%s(): fstat failed\n", __func__); +#endif + return 0; + } + +#ifdef TEST_SHANNON + printf("%s(): st_dev=0x%lx, st_rdev=0x%lx\n", __func__, + (ulong) stat_buff.st_dev, (ulong) stat_buff.st_rdev); +#endif + + for (dev= shannon_devices ; dev->st_dev; dev++) + { +#ifdef TEST_SHANNON + printf("%s(): st_rdev=0x%lx\n", __func__, (ulong) dev->st_dev); +#endif + if (stat_buff.st_dev == dev->st_dev) + return shannon_dev_has_atomic_write(dev, page_size); + } + return 0; +} + + +/*********************************************************************** + Generic atomic write code +************************************************************************/ + +/* + Initalize automic write sub systems. + Checks if we have any devices that supports atomic write +*/ + +void my_init_atomic_write(void) +{ + if ((has_shannon_atomic_write= test_if_shannon_card_exists()) || + (has_fusion_io_atomic_write= test_if_fusion_io_card_exists())) + my_may_have_atomic_write= 1; +#ifdef TEST_SHANNON + printf("%s(): has_shannon_atomic_write=%d, my_may_have_atomic_write=%d\n", + __func__, + has_shannon_atomic_write, + my_may_have_atomic_write); +#endif +} + + +/** + Check if a file supports atomic write + + @return FALSE No atomic write support + TRUE File supports atomic write +*/ + +my_bool my_test_if_atomic_write(File handle, int page_size) +{ +#ifdef TEST_SHANNON + printf("%s(): has_shannon_atomic_write=%d, my_may_have_atomic_write=%d\n", + __func__, + has_shannon_atomic_write, + my_may_have_atomic_write); +#endif + if (!my_may_have_atomic_write) + return 0; + if (has_shannon_atomic_write && + shannon_has_atomic_write(handle, page_size)) + return 1; + + if (has_fusion_io_atomic_write && + fusion_io_has_atomic_write(handle, page_size)) + return 1; + + return 0; +} + +#ifdef TEST_SHANNON +int main() +{ + int fd, ret; + + my_init_atomic_write(); + fd= open("/u01/1.file", O_RDWR); + ret= my_test_if_atomic_write(fd, 4096); + if (ret) + printf("support atomic_write\n"); + else + printf("do not support atomic_write\n"); + close(fd); + return 0; +} +#endif + + +#else /* __linux__ */ + +/* Dummy functions to provide the interfaces for other systems */ + +void my_init_atomic_write(void) +{ +} +#endif /* __linux__ */ diff --git a/mysys/my_bit.c b/mysys/my_bit.c index fdf767fa5be..d3130ea461a 100644 --- a/mysys/my_bit.c +++ b/mysys/my_bit.c @@ -17,24 +17,6 @@ #include <my_bit.h> -const char _my_bits_nbits[256] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, -}; /* perl -e 'print map{", 0x".unpack H2,pack B8,unpack b8,chr$_}(0..255)' diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index ce48b9fdf41..f857101af02 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -168,7 +168,7 @@ static inline uint get_first_set(my_bitmap_map value, uint word_pos) my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, - my_bool thread_safe __attribute__((unused))) + my_bool thread_safe) { DBUG_ENTER("my_bitmap_init"); if (!buf) @@ -255,7 +255,8 @@ my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_lock(map); res= bitmap_fast_test_and_set(map, bitmap_bit); bitmap_unlock(map); @@ -288,7 +289,8 @@ my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_lock(map); res= bitmap_fast_test_and_clear(map, bitmap_bit); bitmap_unlock(map); @@ -317,8 +319,8 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) uint prefix_bytes, prefix_bits, d; uchar *m= (uchar *)map->bitmap; - DBUG_ASSERT(map->bitmap && - (prefix_size <= map->n_bits || prefix_size == (uint) ~0)); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(prefix_size <= map->n_bits || prefix_size == (uint) ~0); set_if_smaller(prefix_size, map->n_bits); if ((prefix_bytes= prefix_size / 8)) memset(m, 0xff, prefix_bytes); @@ -340,7 +342,8 @@ my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) uchar *m= (uchar*) map->bitmap; uchar *end_prefix= m+(prefix_size-1)/8; uchar *end; - DBUG_ASSERT(m && prefix_size <= map->n_bits); + DBUG_ASSERT(m); + DBUG_ASSERT(prefix_size <= map->n_bits); /* Empty prefix is always true */ if (!prefix_size) @@ -393,8 +396,8 @@ my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap && map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while (m1 < end) @@ -412,8 +415,9 @@ my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while (m1 < end) @@ -431,7 +435,8 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; uint len= no_words_in_map(map), len2 = no_words_in_map(map2); - DBUG_ASSERT(map->bitmap && map2->bitmap); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); end= to+MY_MIN(len,len2); while (to < end) @@ -476,7 +481,8 @@ my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array, uint i, j, start_idx, end_idx; my_bitmap_map cur_res; - DBUG_ASSERT(bitmap_count && end_bit >= start_bit); + DBUG_ASSERT(bitmap_count); + DBUG_ASSERT(end_bit >= start_bit); for (j= 0; j < bitmap_count; j++) DBUG_ASSERT(end_bit < bitmap_array[j]->n_bits); @@ -504,8 +510,9 @@ my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2) { my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); + DBUG_ASSERT(map1->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map1->n_bits==map2->n_bits); end= map1->last_word_ptr; while ( m1 < end) if ((*m1++ | *m2++) != 0xFFFFFFFF) @@ -550,8 +557,9 @@ void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits==map2->n_bits); end= map->last_word_ptr; @@ -564,8 +572,9 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); end= map->last_word_ptr; while (to <= end) @@ -576,8 +585,9 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); while (to <= end) *to++ ^= *from++; } @@ -614,8 +624,9 @@ void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(map2->bitmap); + DBUG_ASSERT(map->n_bits == map2->n_bits); end= map->last_word_ptr; while (to <= end) @@ -744,7 +755,8 @@ uint bitmap_lock_set_next(MY_BITMAP *map) void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) { bitmap_lock(map); - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + DBUG_ASSERT(map->bitmap); + DBUG_ASSERT(bitmap_bit < map->n_bits); bitmap_clear_bit(map, bitmap_bit); bitmap_unlock(map); } diff --git a/mysys/my_compare.c b/mysys/my_compare.c index 7e11f5ffb4e..ff704aa40f0 100644 --- a/mysys/my_compare.c +++ b/mysys/my_compare.c @@ -21,12 +21,11 @@ #include <my_sys.h> int ha_compare_text(CHARSET_INFO *charset_info, const uchar *a, uint a_length, - const uchar *b, uint b_length, my_bool part_key, - my_bool skip_end_space) + const uchar *b, uint b_length, my_bool part_key) { if (!part_key) return charset_info->coll->strnncollsp(charset_info, a, a_length, - b, b_length, (my_bool)!skip_end_space); + b, b_length); return charset_info->coll->strnncoll(charset_info, a, a_length, b, b_length, part_key); } @@ -186,8 +185,7 @@ int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, if (piks && (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0), - (my_bool)!(nextflag & SEARCH_PREFIX)))) + next_key_length <= 0)))) return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); a+=a_length; b+=b_length; @@ -199,8 +197,7 @@ int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, if (piks && (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0), - (my_bool)!(nextflag & SEARCH_PREFIX)))) + next_key_length <= 0)))) return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); a=end; b+=length; @@ -247,12 +244,7 @@ int ha_key_cmp(HA_KEYSEG *keyseg, const uchar *a, if (piks && (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length, (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0), - (my_bool) ((nextflag & (SEARCH_FIND | - SEARCH_UPDATE)) == - SEARCH_FIND && - ! (keyseg->flag & - HA_END_SPACE_ARE_EQUAL))))) + next_key_length <= 0)))) return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); a+= a_length; b+= b_length; diff --git a/mysys/my_context.c b/mysys/my_context.c index 29ba9f79c72..cf10738bdbd 100644 --- a/mysys/my_context.c +++ b/mysys/my_context.c @@ -24,7 +24,7 @@ #include "m_string.h" #include "my_context.h" -#ifdef HAVE_VALGRIND +#ifdef HAVE_VALGRIND_MEMCHECK_H #include <valgrind/valgrind.h> #endif @@ -134,7 +134,7 @@ my_context_init(struct my_context *c, size_t stack_size) if (!(c->stack= malloc(stack_size))) return -1; /* Out of memory */ c->stack_size= stack_size; -#ifdef HAVE_VALGRIND +#ifdef HAVE_VALGRIND_MEMCHECK_H c->valgrind_stack_id= VALGRIND_STACK_REGISTER(c->stack, ((unsigned char *)(c->stack))+stack_size); #endif @@ -146,7 +146,7 @@ my_context_destroy(struct my_context *c) { if (c->stack) { -#ifdef HAVE_VALGRIND +#ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id); #endif free(c->stack); @@ -385,7 +385,7 @@ my_context_init(struct my_context *c, size_t stack_size) (( ((intptr)c->stack_bot + stack_size) & ~(intptr)0xf) - 16); bzero(c->stack_top, 16); -#ifdef HAVE_VALGRIND +#ifdef HAVE_VALGRIND_MEMCHECK_H c->valgrind_stack_id= VALGRIND_STACK_REGISTER(c->stack_bot, c->stack_top); #endif @@ -398,7 +398,7 @@ my_context_destroy(struct my_context *c) if (c->stack_bot) { free(c->stack_bot); -#ifdef HAVE_VALGRIND +#ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id); #endif } @@ -621,7 +621,7 @@ my_context_init(struct my_context *c, size_t stack_size) (( ((intptr)c->stack_bot + stack_size) & ~(intptr)0xf) - 16); bzero(c->stack_top, 16); -#ifdef HAVE_VALGRIND +#ifdef HAVE_VALGRIND_MEMCHECK_H c->valgrind_stack_id= VALGRIND_STACK_REGISTER(c->stack_bot, c->stack_top); #endif @@ -634,7 +634,7 @@ my_context_destroy(struct my_context *c) if (c->stack_bot) { free(c->stack_bot); -#ifdef HAVE_VALGRIND +#ifdef HAVE_VALGRIND_MEMCHECK_H VALGRIND_STACK_DEREGISTER(c->valgrind_stack_id); #endif } diff --git a/mysys/my_crc32.c b/mysys/my_crc32.c deleted file mode 100644 index 3fa8c4b83eb..00000000000 --- a/mysys/my_crc32.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (c) 2003, 2004 MySQL AB - Use is subject to license terms - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */ - -#include "mysys_priv.h" - -#ifndef HAVE_COMPRESS -#undef DYNAMIC_CRC_TABLE -#include "../zlib/crc32.c" -#endif - diff --git a/mysys/my_default.c b/mysys/my_default.c index 6f080bb35fe..c1d971f5062 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -174,8 +174,8 @@ fn_expand(const char *filename, char *result_buf) char dir[FN_REFLEN]; const int flags= MY_UNPACK_FILENAME | MY_SAFE_PATH | MY_RELATIVE_PATH; DBUG_ENTER("fn_expand"); - DBUG_PRINT("enter", ("filename: %s, result_buf: 0x%lx", - filename, (unsigned long) result_buf)); + DBUG_PRINT("enter", ("filename: %s, result_buf: %p", + filename, result_buf)); if (my_getwd(dir, sizeof(dir), MYF(0))) DBUG_RETURN(3); DBUG_PRINT("debug", ("dir: %s", dir)); @@ -565,7 +565,7 @@ int my_load_defaults(const char *conf_file, const char **groups, for (; *groups ; groups++) group.count++; - if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32, MYF(0))) + if (my_init_dynamic_array(&args, sizeof(char*), 128, 64, MYF(0))) goto err; ctx.alloc= &alloc; @@ -1135,43 +1135,7 @@ static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs) return 0; } - #ifdef __WIN__ -/* - This wrapper for GetSystemWindowsDirectory() will dynamically bind to the - function if it is available, emulate it on NT4 Terminal Server by stripping - the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just - return GetSystemDirectory(). - */ - -typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT); - -static size_t my_get_system_windows_directory(char *buffer, size_t size) -{ - size_t count; - GET_SYSTEM_WINDOWS_DIRECTORY - func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY) - GetProcAddress(GetModuleHandle("kernel32.dll"), - "GetSystemWindowsDirectoryA"); - - if (func_ptr) - return func_ptr(buffer, (uint) size); - - /* - Windows NT 4.0 Terminal Server Edition: - To retrieve the shared Windows directory, call GetSystemDirectory and - trim the "System32" element from the end of the returned path. - */ - count= GetSystemDirectory(buffer, (uint) size); - if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0) - { - count-= 8; - buffer[count] = '\0'; - } - return count; -} - - static const char *my_get_module_parent(char *buf, size_t size) { char *last= NULL; @@ -1220,7 +1184,7 @@ static const char **init_default_directories(MEM_ROOT *alloc) { char fname_buffer[FN_REFLEN]; - if (my_get_system_windows_directory(fname_buffer, sizeof(fname_buffer))) + if (GetSystemWindowsDirectory(fname_buffer, sizeof(fname_buffer))) errors += add_directory(alloc, fname_buffer, dirs); if (GetWindowsDirectory(fname_buffer, sizeof(fname_buffer))) diff --git a/mysys/my_delete.c b/mysys/my_delete.c index 28889df280b..4201c252715 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -18,6 +18,7 @@ #include <my_sys.h> #ifdef _WIN32 +#include <direct.h> /* rmdir */ static int my_win_unlink(const char *name); #endif @@ -160,3 +161,63 @@ error: DBUG_RETURN(-1); } #endif + +/* + Remove directory recursively. +*/ +int my_rmtree(const char *dir, myf MyFlags) +{ + char path[FN_REFLEN]; + char sep[] = { FN_LIBCHAR, 0 }; + int err = 0; + uint i; + + MY_DIR *dir_info = my_dir(dir, MYF(MY_DONT_SORT | MY_WANT_STAT)); + if (!dir_info) + return 1; + + for (i = 0; i < dir_info->number_of_files; i++) + { + FILEINFO *file = dir_info->dir_entry + i; + /* Skip "." and ".." */ + if (!strcmp(file->name, ".") || !strcmp(file->name, "..")) + continue; + + strxnmov(path, sizeof(path), dir, sep, file->name, NULL); + + if (!MY_S_ISDIR(file->mystat->st_mode)) + { + err = my_delete(path, MyFlags); +#ifdef _WIN32 + /* + On Windows, check and possible reset readonly attribute. + my_delete(), or DeleteFile does not remove theses files. + */ + if (err) + { + DWORD attr = GetFileAttributes(path); + if (attr != INVALID_FILE_ATTRIBUTES && + (attr & FILE_ATTRIBUTE_READONLY)) + { + SetFileAttributes(path, attr &~FILE_ATTRIBUTE_READONLY); + err = my_delete(path, MyFlags); + } + } +#endif + } + else + err = my_rmtree(path, MyFlags); + + if (err) + break; + } + + my_dirend(dir_info); + + if (!err) + err = rmdir(dir); + + return err; +} + + diff --git a/mysys/my_error.c b/mysys/my_error.c index ce20c8067ec..5f1ca0af55b 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -49,7 +49,7 @@ static struct my_err_head { struct my_err_head *meh_next; /* chain link */ - const char** (*get_errmsgs)(); /* returns error message format */ + const char** (*get_errmsgs)(int nr); /* returns error message format */ uint meh_first; /* error number matching array slot 0 */ uint meh_last; /* error number matching last slot */ } my_errmsgs_globerrs= @@ -86,7 +86,7 @@ const char *my_get_err_msg(uint nr) we return NULL. */ if (!(format= (meh_p && (nr >= meh_p->meh_first)) ? - meh_p->get_errmsgs()[nr - meh_p->meh_first] : NULL) || + meh_p->get_errmsgs(nr)[nr - meh_p->meh_first] : NULL) || !*format) return NULL; @@ -131,7 +131,7 @@ void my_error(uint nr, myf MyFlags, ...) Print an error message. @note - Goes through the (sole) function registered in error_handler_hook + Just like my_error, but for cases when the error message is not ER(error) @param error error number @param format format string @@ -217,7 +217,8 @@ void my_message(uint error, const char *str, register myf MyFlags) @retval != 0 Error */ -int my_error_register(const char** (*get_errmsgs) (void), uint first, uint last) +int my_error_register(const char** (*get_errmsgs)(int error), uint first, + uint last) { struct my_err_head *meh_p; struct my_err_head **search_meh_pp; @@ -273,11 +274,10 @@ int my_error_register(const char** (*get_errmsgs) (void), uint first, uint last) @retval non-NULL OK, returns address of error messages pointers array. */ -const char **my_error_unregister(uint first, uint last) +my_bool my_error_unregister(uint first, uint last) { struct my_err_head *meh_p; struct my_err_head **search_meh_pp; - const char **errmsgs; /* Search for the registration in the list. */ for (search_meh_pp= &my_errmsgs_list; @@ -289,17 +289,15 @@ const char **my_error_unregister(uint first, uint last) break; } if (! *search_meh_pp) - return NULL; - + return TRUE; + /* Remove header from the chain. */ meh_p= *search_meh_pp; *search_meh_pp= meh_p->meh_next; - /* Save the return value and free the header. */ - errmsgs= meh_p->get_errmsgs(); my_free(meh_p); - return errmsgs; + return FALSE; } diff --git a/mysys/my_fopen.c b/mysys/my_fopen.c index e962b9d03a4..924d219c3a8 100644 --- a/mysys/my_fopen.c +++ b/mysys/my_fopen.c @@ -74,7 +74,7 @@ FILE *my_fopen(const char *filename, int flags, myf MyFlags) my_file_total_opened++; my_file_info[filedesc].type= STREAM_BY_FOPEN; mysql_mutex_unlock(&THR_LOCK_open); - DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); + DBUG_PRINT("exit",("stream: %p", fd)); DBUG_RETURN(fd); } else @@ -222,7 +222,7 @@ int my_fclose(FILE *fd, myf MyFlags) { int err,file; DBUG_ENTER("my_fclose"); - DBUG_PRINT("my",("stream: 0x%lx MyFlags: %lu", (long) fd, MyFlags)); + DBUG_PRINT("my",("stream: %p MyFlags: %lu", fd, MyFlags)); mysql_mutex_lock(&THR_LOCK_open); file= my_fileno(fd); @@ -292,7 +292,7 @@ FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) mysql_mutex_unlock(&THR_LOCK_open); } - DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); + DBUG_PRINT("exit",("stream: %p", fd)); DBUG_RETURN(fd); } /* my_fdopen */ diff --git a/mysys/my_fstream.c b/mysys/my_fstream.c index 9c8edb644d4..8a6db2e8502 100644 --- a/mysys/my_fstream.c +++ b/mysys/my_fstream.c @@ -46,8 +46,8 @@ size_t my_fread(FILE *stream, uchar *Buffer, size_t Count, myf MyFlags) { size_t readbytes; DBUG_ENTER("my_fread"); - DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %lu", - (long) stream, (long) Buffer, (uint) Count, MyFlags)); + DBUG_PRINT("my",("stream: %p Buffer %p Count: %u MyFlags: %lu", + stream, Buffer, (uint) Count, MyFlags)); if ((readbytes= fread(Buffer, sizeof(char), Count, stream)) != Count) { @@ -94,8 +94,8 @@ size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags) uint errors; #endif DBUG_ENTER("my_fwrite"); - DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %lu", - (long) stream, (long) Buffer, (uint) Count, MyFlags)); + DBUG_PRINT("my",("stream:%p Buffer:%p Count: %u MyFlags: %lu", + stream, Buffer, (uint) Count, MyFlags)); #if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) errors=0; @@ -163,8 +163,8 @@ my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, myf MyFlags __attribute__((unused))) { DBUG_ENTER("my_fseek"); - DBUG_PRINT("my",("stream: 0x%lx pos: %lu whence: %d MyFlags: %lu", - (long) stream, (long) pos, whence, MyFlags)); + DBUG_PRINT("my",("stream:%p pos: %llu whence: %d MyFlags: %lu", + stream, (ulonglong) pos, whence, MyFlags)); DBUG_RETURN(fseek(stream, (off_t) pos, whence) ? MY_FILEPOS_ERROR : (my_off_t) ftell(stream)); } /* my_seek */ @@ -174,11 +174,11 @@ my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused))) { - off_t pos; + long long pos; DBUG_ENTER("my_ftell"); - DBUG_PRINT("my",("stream: 0x%lx MyFlags: %lu", (long) stream, MyFlags)); - pos=ftell(stream); - DBUG_PRINT("exit",("ftell: %lu",(ulong) pos)); + DBUG_PRINT("my",("stream:%p MyFlags: %lu", stream, MyFlags)); + pos=IF_WIN(_ftelli64(stream),ftell(stream)); + DBUG_PRINT("exit",("ftell: %lld",pos)); DBUG_RETURN((my_off_t) pos); } /* my_ftell */ diff --git a/mysys/my_getncpus.c b/mysys/my_getncpus.c index 38585161c22..0d081b72d11 100644 --- a/mysys/my_getncpus.c +++ b/mysys/my_getncpus.c @@ -21,30 +21,65 @@ #include <unistd.h> #endif +#if defined(__FreeBSD__) && defined(HAVE_PTHREAD_GETAFFINITY_NP) +#include <pthread_np.h> +#include <sys/cpuset.h> +#endif + static int ncpus=0; -int my_getncpus() +int my_getncpus(void) { if (!ncpus) { + /* + First attempt to get the total number of available cores. sysconf is + the fallback, but it can return a larger number. It will return the + total number of cores, not the ones available to the process - as + configured via core affinity. + */ +#if (defined(__linux__) || defined(__FreeBSD__)) && defined(HAVE_PTHREAD_GETAFFINITY_NP) +#ifdef __linux__ + cpu_set_t set; +#else + cpuset_t set; +#endif + if (pthread_getaffinity_np(pthread_self(), sizeof(set), &set) == 0) + { +#ifdef CPU_COUNT + /* CPU_COUNT was introduced with glibc 2.6. */ + ncpus= CPU_COUNT(&set); +#else + /* Implementation for platforms with glibc < 2.6 */ + size_t i; + + for (i= 0; i < CPU_SETSIZE; i++) + if (CPU_ISSET(i, &set)) + ncpus++; +#endif + return ncpus; + } +#endif /* (__linux__ || __FreeBSD__) && HAVE_PTHREAD_GETAFFINITY_NP */ + #ifdef _SC_NPROCESSORS_ONLN ncpus= sysconf(_SC_NPROCESSORS_ONLN); #elif defined(__WIN__) SYSTEM_INFO sysinfo; /* - * We are not calling GetNativeSystemInfo here because (1) we - * don't believe that they return different values for number - * of processors and (2) if WOW64 limits processors for Win32 - * then we don't want to try to override that. + We are not calling GetNativeSystemInfo here because (1) we + don't believe that they return different values for number + of processors and (2) if WOW64 limits processors for Win32 + then we don't want to try to override that. */ GetSystemInfo(&sysinfo); ncpus= sysinfo.dwNumberOfProcessors; #else - /* unknown so play safe: assume SMP and forbid uniprocessor build */ + /* Unknown so play safe: assume SMP and forbid uniprocessor build */ ncpus= 2; #endif } + return ncpus; } diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 980a24882d4..13d0d7c240e 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -1400,7 +1400,7 @@ static uint print_name(const struct my_option *optp) for (;*s;s++) putchar(*s == '_' ? '-' : *s); - return s - optp->name; + return (uint)(s - optp->name); } /** prints option comment with indentation and wrapping. @@ -1441,7 +1441,7 @@ static uint print_comment(const char *comment, putchar(' '); } printf("%s", comment); - return curpos + (end - comment); + return curpos + (int)(end - comment); } diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index a6eb5f6581f..c4f18b51f35 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -48,8 +48,8 @@ int my_getwd(char * buf, size_t size, myf MyFlags) { char * pos; DBUG_ENTER("my_getwd"); - DBUG_PRINT("my",("buf: 0x%lx size: %u MyFlags %lu", - (long) buf, (uint) size, MyFlags)); + DBUG_PRINT("my",("buf:%p size: %u MyFlags %lu", + buf, (uint) size, MyFlags)); if (size < 1) DBUG_RETURN(-1); diff --git a/mysys/my_init.c b/mysys/my_init.c index d1ed42c9f19..eb7623f75b6 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -253,8 +253,6 @@ void my_parameter_handler(const wchar_t * expression, const wchar_t * function, const wchar_t * file, unsigned int line, uintptr_t pReserved) { - DBUG_PRINT("my",("Expression: %s function: %s file: %s, line: %d", - expression, function, file, line)); __debugbreak(); } diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c index c5e33388e2a..33d0843cd58 100644 --- a/mysys/my_largepage.c +++ b/mysys/my_largepage.c @@ -15,7 +15,7 @@ #include "mysys_priv.h" -#ifdef HAVE_LARGE_PAGES +#ifdef HAVE_LINUX_LARGE_PAGES #ifdef HAVE_SYS_IPC_H #include <sys/ipc.h> @@ -163,4 +163,4 @@ my_bool my_large_free_int(uchar *ptr) } #endif /* HAVE_DECL_SHM_HUGETLB */ -#endif /* HAVE_LARGE_PAGES */ +#endif /* HAVE_LINUX_LARGE_PAGES */ diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 977352345c1..c40b75e1faf 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2008, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -109,7 +110,7 @@ static char *directory_file_name (char * dst, const char *src) MY_DIR *my_dir(const char *path, myf MyFlags) { - MY_DIR_HANDLE *dirh= 0; + MY_DIR_HANDLE *dirh; FILEINFO finfo; DIR *dirp; struct dirent *dp; @@ -122,10 +123,13 @@ MY_DIR *my_dir(const char *path, myf MyFlags) tmp_file= directory_file_name(tmp_path, path); if (!(dirp= opendir(tmp_path))) - goto error; + { + my_errno= errno; + goto err_open; + } if (!(dirh= my_malloc(sizeof(*dirh), MyFlags | MY_ZEROFILL))) - goto error; + goto err_alloc; if (my_init_dynamic_array(&dirh->array, sizeof(FILEINFO), ENTRIES_START_SIZE, ENTRIES_INCREMENT, @@ -179,11 +183,11 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DBUG_RETURN(&dirh->dir); - error: - my_errno=errno; - if (dirp) - (void) closedir(dirp); +error: my_dirend(&dirh->dir); +err_alloc: + (void) closedir(dirp); +err_open: if (MyFlags & (MY_FAE | MY_WME)) my_error(EE_DIR, MYF(ME_BELL | ME_WAITTANG), path, my_errno); DBUG_RETURN(NULL); @@ -211,7 +215,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) long handle; #endif DBUG_ENTER("my_dir"); - DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); + DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags)); /* Put LIB-CHAR as last path-character if not there */ tmp_file=tmp_path; @@ -337,8 +341,8 @@ MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) { int m_used; DBUG_ENTER("my_stat"); - DBUG_PRINT("my", ("path: '%s' stat_area: 0x%lx MyFlags: %lu", path, - (long) stat_area, my_flags)); + DBUG_PRINT("my", ("path: '%s' stat_area: %p MyFlags: %lu", path, + stat_area, my_flags)); if ((m_used= (stat_area == NULL))) if (!(stat_area= (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 08285738528..9d3fdb3e0ee 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -68,6 +68,8 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, if (readbytes != Count) { + /* We should never read with wrong file descriptor! */ + DBUG_ASSERT(readbytes != (size_t)-1 || errno != EBADF); my_errno= errno; if (errno == 0 || (readbytes != (size_t) -1 && (MyFlags & (MY_NABP | MY_FNABP)))) diff --git a/mysys/my_rdtsc.c b/mysys/my_rdtsc.c index afb97553dd7..b020e224a59 100644 --- a/mysys/my_rdtsc.c +++ b/mysys/my_rdtsc.c @@ -812,7 +812,11 @@ void my_timer_init(MY_TIMER_INFO *mti) time1= my_timer_cycles(); time2= my_timer_ticks(); time3= time2; /* Avoids a Microsoft/IBM compiler warning */ +#if defined(HAVE_SYS_TIMES_H) && defined(HAVE_TIMES) + for (i= 0; i < 1000; ++i) +#else for (i= 0; i < MY_TIMER_ITERATIONS * 1000; ++i) +#endif { time3= my_timer_ticks(); if (time3 - time2 > 10) break; diff --git a/mysys/my_safehash.c b/mysys/my_safehash.c index e4e72bd6506..7555f73fb30 100644 --- a/mysys/my_safehash.c +++ b/mysys/my_safehash.c @@ -166,7 +166,7 @@ uchar *safe_hash_search(SAFE_HASH *hash, const uchar *key, uint length, result= def; else result= ((SAFE_HASH_ENTRY*) result)->data; - DBUG_PRINT("exit",("data: 0x%lx", (long) result)); + DBUG_PRINT("exit",("data: %p", result)); DBUG_RETURN(result); } @@ -197,7 +197,7 @@ my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length, SAFE_HASH_ENTRY *entry; my_bool error= 0; DBUG_ENTER("safe_hash_set"); - DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, (long) data)); + DBUG_PRINT("enter",("key: %.*s data: %p", length, key, data)); mysql_rwlock_wrlock(&hash->mutex); entry= (SAFE_HASH_ENTRY*) my_hash_search(&hash->hash, key, length); diff --git a/mysys/my_static.c b/mysys/my_static.c index 845d3e9612f..8916b42f9fb 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -59,7 +59,7 @@ USED_MEM* my_once_root_block=0; /* pointer to first block */ uint my_once_extra=ONCE_ALLOC_INIT; /* Memory to alloc / block */ /* from my_largepage.c */ -#ifdef HAVE_LARGE_PAGES +#ifdef HAVE_LINUX_LARGE_PAGES my_bool my_use_large_pages= 0; uint my_large_page_size= 0; #endif @@ -99,3 +99,10 @@ my_bool my_disable_async_io=0; my_bool my_disable_flush_key_blocks=0; my_bool my_disable_symlinks=0; my_bool my_disable_copystat_in_redel=0; + +/* Typelib by all clients */ +const char *sql_protocol_names_lib[] = +{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS }; + +TYPELIB sql_protocol_typelib ={ array_elements(sql_protocol_names_lib) - 1, "", + sql_protocol_names_lib, NULL }; diff --git a/mysys/my_sync.c b/mysys/my_sync.c index 2ed62e4541a..5a21a511dda 100644 --- a/mysys/my_sync.c +++ b/mysys/my_sync.c @@ -133,8 +133,6 @@ int my_sync(File fd, myf my_flags) } /* my_sync */ -static const char cur_dir_name[]= {FN_CURLIB, 0}; - /* Force directory information to disk. @@ -151,6 +149,7 @@ int my_sync_dir(const char *dir_name __attribute__((unused)), myf my_flags __attribute__((unused))) { #ifdef NEED_EXPLICIT_SYNC_DIR + static const char cur_dir_name[]= {FN_CURLIB, 0}; File dir_fd; int res= 0; const char *correct_dir_name; diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index cc47bfc72d0..5686dabf35d 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -141,7 +141,7 @@ void my_thread_global_reinit(void) my_thread_destroy_internal_mutex(); my_thread_init_internal_mutex(); - tmp= my_pthread_getspecific(struct st_my_thread_var*, THR_KEY_mysys); + tmp= my_thread_var; DBUG_ASSERT(tmp); my_thread_destory_thr_mutex(tmp); @@ -279,7 +279,7 @@ my_bool my_thread_init(void) fprintf(stderr,"my_thread_init(): pthread_self: %p\n", pthread_self()); #endif - if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) + if (my_thread_var) { #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n", @@ -297,7 +297,7 @@ my_bool my_thread_init(void) error= 1; goto end; } - pthread_setspecific(THR_KEY_mysys,tmp); + set_mysys_var(tmp); tmp->pthread_self= pthread_self(); my_thread_init_thr_mutex(tmp); @@ -305,7 +305,7 @@ my_bool my_thread_init(void) STACK_DIRECTION * (long)my_thread_stack_size; mysql_mutex_lock(&THR_LOCK_threads); - tmp->id= ++thread_id; + tmp->id= tmp->dbug_id= ++thread_id; ++THR_thread_count; mysql_mutex_unlock(&THR_LOCK_threads); tmp->init= 1; @@ -334,7 +334,7 @@ end: void my_thread_end(void) { struct st_my_thread_var *tmp; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; #ifdef EXTRA_DEBUG_THREADS fprintf(stderr,"my_thread_end(): tmp: %p pthread_self: %p thread_id: %ld\n", @@ -357,7 +357,7 @@ void my_thread_end(void) as the key is used by DBUG. */ DBUG_POP(); - pthread_setspecific(THR_KEY_mysys,0); + set_mysys_var(NULL); if (tmp && tmp->init) { @@ -410,7 +410,7 @@ my_thread_id my_thread_dbug_id() my_thread_init(). */ struct st_my_thread_var *tmp= my_thread_var; - return tmp ? tmp->id : 0; + return tmp ? tmp->dbug_id : 0; } #ifdef DBUG_OFF @@ -441,7 +441,7 @@ extern void **my_thread_var_dbug() struct st_my_thread_var *tmp; if (!my_thread_global_init_done) return NULL; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; return tmp && tmp->init ? &tmp->dbug : 0; } #endif /* DBUG_OFF */ @@ -453,7 +453,7 @@ safe_mutex_t **my_thread_var_mutex_in_use() struct st_my_thread_var *tmp; if (!my_thread_global_init_done) return NULL; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); + tmp= my_thread_var; return tmp ? &tmp->mutex_in_use : 0; } diff --git a/mysys/my_wincond.c b/mysys/my_wincond.c index d68de3f4d03..c2814e37b93 100644 --- a/mysys/my_wincond.c +++ b/mysys/my_wincond.c @@ -26,63 +26,6 @@ #include <sys/timeb.h> -/* - Windows native condition variables. We use runtime loading / function - pointers, because they are not available on XP -*/ - -/* Prototypes and function pointers for condition variable functions */ -typedef void (WINAPI * InitializeConditionVariableProc) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI * SleepConditionVariableCSProc) - (PCONDITION_VARIABLE ConditionVariable, - PCRITICAL_SECTION CriticalSection, - DWORD dwMilliseconds); - -typedef void (WINAPI * WakeAllConditionVariableProc) - (PCONDITION_VARIABLE ConditionVariable); - -typedef void (WINAPI * WakeConditionVariableProc) - (PCONDITION_VARIABLE ConditionVariable); - -static InitializeConditionVariableProc my_InitializeConditionVariable; -static SleepConditionVariableCSProc my_SleepConditionVariableCS; -static WakeAllConditionVariableProc my_WakeAllConditionVariable; -static WakeConditionVariableProc my_WakeConditionVariable; - - -/** - Indicates if we have native condition variables, - initialized first time pthread_cond_init is called. -*/ - -static BOOL have_native_conditions= FALSE; - - -/** - Check if native conditions can be used, load function pointers -*/ - -static void check_native_cond_availability(void) -{ - HMODULE module= GetModuleHandle("kernel32"); - - my_InitializeConditionVariable= (InitializeConditionVariableProc) - GetProcAddress(module, "InitializeConditionVariable"); - my_SleepConditionVariableCS= (SleepConditionVariableCSProc) - GetProcAddress(module, "SleepConditionVariableCS"); - my_WakeAllConditionVariable= (WakeAllConditionVariableProc) - GetProcAddress(module, "WakeAllConditionVariable"); - my_WakeConditionVariable= (WakeConditionVariableProc) - GetProcAddress(module, "WakeConditionVariable"); - - if (my_InitializeConditionVariable) - have_native_conditions= TRUE; -} - - - /** Convert abstime to milliseconds */ @@ -105,202 +48,40 @@ static DWORD get_milliseconds(const struct timespec *abstime) return (DWORD)ms; } - -/* - Old (pre-vista) implementation using events -*/ - -static int legacy_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) -{ - cond->waiting= 0; - InitializeCriticalSection(&cond->lock_waiting); - - cond->events[SIGNAL]= CreateEvent(NULL, /* no security */ - FALSE, /* auto-reset event */ - FALSE, /* non-signaled initially */ - NULL); /* unnamed */ - - /* Create a manual-reset event. */ - cond->events[BROADCAST]= CreateEvent(NULL, /* no security */ - TRUE, /* manual-reset */ - FALSE, /* non-signaled initially */ - NULL); /* unnamed */ - - - cond->broadcast_block_event= CreateEvent(NULL, /* no security */ - TRUE, /* manual-reset */ - TRUE, /* signaled initially */ - NULL); /* unnamed */ - - if( cond->events[SIGNAL] == NULL || - cond->events[BROADCAST] == NULL || - cond->broadcast_block_event == NULL ) - return ENOMEM; - return 0; -} - - -static int legacy_cond_destroy(pthread_cond_t *cond) -{ - DeleteCriticalSection(&cond->lock_waiting); - - if (CloseHandle(cond->events[SIGNAL]) == 0 || - CloseHandle(cond->events[BROADCAST]) == 0 || - CloseHandle(cond->broadcast_block_event) == 0) - return EINVAL; - return 0; -} - - -static int legacy_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - struct timespec *abstime) -{ - int result; - DWORD timeout; - - timeout= get_milliseconds(abstime); - /* - Block access if previous broadcast hasn't finished. - This is just for safety and should normally not - affect the total time spent in this function. - */ - WaitForSingleObject(cond->broadcast_block_event, INFINITE); - - EnterCriticalSection(&cond->lock_waiting); - cond->waiting++; - LeaveCriticalSection(&cond->lock_waiting); - - LeaveCriticalSection(mutex); - result= WaitForMultipleObjects(2, cond->events, FALSE, timeout); - - EnterCriticalSection(&cond->lock_waiting); - cond->waiting--; - - if (cond->waiting == 0) - { - /* - We're the last waiter to be notified or to stop waiting, so - reset the manual event. - */ - /* Close broadcast gate */ - ResetEvent(cond->events[BROADCAST]); - /* Open block gate */ - SetEvent(cond->broadcast_block_event); - } - LeaveCriticalSection(&cond->lock_waiting); - - EnterCriticalSection(mutex); - - return result == WAIT_TIMEOUT ? ETIMEDOUT : 0; -} - -static int legacy_cond_signal(pthread_cond_t *cond) -{ - EnterCriticalSection(&cond->lock_waiting); - - if(cond->waiting > 0) - SetEvent(cond->events[SIGNAL]); - - LeaveCriticalSection(&cond->lock_waiting); - - return 0; -} - - -static int legacy_cond_broadcast(pthread_cond_t *cond) -{ - EnterCriticalSection(&cond->lock_waiting); - /* - The mutex protect us from broadcasting if - there isn't any thread waiting to open the - block gate after this call has closed it. - */ - if(cond->waiting > 0) - { - /* Close block gate */ - ResetEvent(cond->broadcast_block_event); - /* Open broadcast gate */ - SetEvent(cond->events[BROADCAST]); - } - - LeaveCriticalSection(&cond->lock_waiting); - - return 0; -} - - -/* - Posix API functions. Just choose between native and legacy implementation. -*/ - int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { - /* - Once initialization is used here rather than in my_init(), to - 1) avoid my_init() pitfalls- undefined order in which initialization should - run - 2) be potentially useful C++ (in static constructors that run before main()) - 3) just to simplify the API. - Also, the overhead of my_pthread_once is very small. - */ - static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT; - my_pthread_once(&once_control, check_native_cond_availability); - - if (have_native_conditions) - { - my_InitializeConditionVariable(&cond->native_cond); - return 0; - } - else - return legacy_cond_init(cond, attr); + InitializeConditionVariable(cond); + return 0; } int pthread_cond_destroy(pthread_cond_t *cond) { - if (have_native_conditions) - return 0; /* no destroy function */ - else - return legacy_cond_destroy(cond); + return 0; } int pthread_cond_broadcast(pthread_cond_t *cond) { - if (have_native_conditions) - { - my_WakeAllConditionVariable(&cond->native_cond); - return 0; - } - else - return legacy_cond_broadcast(cond); + WakeAllConditionVariable(cond); + return 0; } int pthread_cond_signal(pthread_cond_t *cond) { - if (have_native_conditions) - { - my_WakeConditionVariable(&cond->native_cond); - return 0; - } - else - return legacy_cond_signal(cond); + WakeConditionVariable(cond); + return 0; } int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { - if (have_native_conditions) - { - DWORD timeout= get_milliseconds(abstime); - if (!my_SleepConditionVariableCS(&cond->native_cond, mutex, timeout)) - return ETIMEDOUT; - return 0; - } - else - return legacy_cond_timedwait(cond, mutex, abstime); + DWORD timeout= get_milliseconds(abstime); + if (!SleepConditionVariableCS(cond, mutex, timeout)) + return ETIMEDOUT; + return 0; } diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index 725bd6ac31f..4f8f5dcf44b 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -121,6 +121,15 @@ int pthread_join(pthread_t thread, void **value_ptr) goto error_return; } + if (!GetExitCodeThread(handle, &ret)) + { + errno= EINVAL; + goto error_return; + } + + if (value_ptr) + *value_ptr= (void *)(size_t)ret; + CloseHandle(handle); return 0; @@ -149,45 +158,22 @@ int pthread_cancel(pthread_t thread) return -1; } + + /* - One time initialization. For simplicity, we assume initializer thread - does not exit within init_routine(). + One time initialization. */ -int my_pthread_once(my_pthread_once_t *once_control, - void (*init_routine)(void)) -{ - LONG state; - - /* - Do "dirty" read to find out if initialization is already done, to - save an interlocked operation in common case. Memory barriers are ensured by - Visual C++ volatile implementation. - */ - if (*once_control == MY_PTHREAD_ONCE_DONE) - return 0; - state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS, - MY_PTHREAD_ONCE_INIT); +static BOOL CALLBACK init_once_callback(my_pthread_once_t *once_control, PVOID param, PVOID *context) +{ + typedef void(*void_f)(void); + ((void_f)param)(); + return TRUE; +} - switch(state) - { - case MY_PTHREAD_ONCE_INIT: - /* This is initializer thread */ - (*init_routine)(); - *once_control= MY_PTHREAD_ONCE_DONE; - break; - - case MY_PTHREAD_ONCE_INPROGRESS: - /* init_routine in progress. Wait for its completion */ - while(*once_control == MY_PTHREAD_ONCE_INPROGRESS) - { - Sleep(1); - } - break; - case MY_PTHREAD_ONCE_DONE: - /* Nothing to do */ - break; - } +int my_pthread_once(my_pthread_once_t *once_control, void (*func)(void)) +{ + InitOnceExecuteOnce(once_control, init_once_callback, func, NULL); return 0; } #endif diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index c439dadbd99..47ba8a0d920 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -55,6 +55,9 @@ struct st_irem struct st_irem *next; /* Linked list of structures */ struct st_irem *prev; /* Other link */ size_t datasize; /* Size requested */ +#if SIZEOF_SIZE_T == 4 + size_t pad; /* Compensate 32bit datasize */ +#endif #ifdef HAVE_BACKTRACE void *frame[SF_REMEMBER_FRAMES]; /* call stack */ #endif @@ -375,7 +378,7 @@ void sf_report_leaked_memory(my_thread_id id) { my_thread_id tid = irem->thread_id && irem->flags & MY_THREAD_SPECIFIC ? irem->thread_id : 0; - fprintf(stderr, "Warning: %4lu bytes lost at %p, allocated by T@%lu at ", + fprintf(stderr, "Warning: %4lu bytes lost at %p, allocated by T@%llu at ", (ulong) irem->datasize, (char*) (irem + 1), tid); print_stack(irem->frame); total+= irem->datasize; diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c index 339111f6fee..86cf272a437 100644 --- a/mysys/stacktrace.c +++ b/mysys/stacktrace.c @@ -34,11 +34,6 @@ #include <execinfo.h> #endif -void my_init_stacktrace() -{ -} - - /* Attempt to print a char * pointer as a string. @@ -393,7 +388,18 @@ void my_write_core(int sig) #else /* __WIN__*/ +#ifdef _MSC_VER +/* Silence warning in OS header dbghelp.h */ +#pragma warning(push) +#pragma warning(disable : 4091) +#endif + #include <dbghelp.h> + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + #include <tlhelp32.h> #include <my_sys.h> #if _MSC_VER @@ -405,11 +411,6 @@ static EXCEPTION_POINTERS *exception_ptrs; #define MODULE64_SIZE_WINXP 576 #define STACKWALK_MAX_FRAMES 64 -void my_init_stacktrace() -{ -} - - void my_set_exception_pointers(EXCEPTION_POINTERS *ep) { exception_ptrs = ep; diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index c23ff62f2db..03412cf5663 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -465,9 +465,10 @@ void thr_lock_delete(THR_LOCK *lock) } -void thr_lock_info_init(THR_LOCK_INFO *info) +void thr_lock_info_init(THR_LOCK_INFO *info, struct st_my_thread_var *tmp) { - struct st_my_thread_var *tmp= my_thread_var; + if (tmp) + tmp= my_thread_var; info->thread= tmp->pthread_self; info->thread_id= tmp->id; } @@ -497,7 +498,6 @@ has_old_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner) return 0; } - static void wake_up_waiters(THR_LOCK *lock); @@ -760,9 +760,9 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) PSI_TABLE_LOCK, lock_type); mysql_mutex_lock(&lock->mutex); - DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx type: %d", - (long) data, data->owner->thread_id, - (long) lock, (int) lock_type)); + DBUG_PRINT("lock",("data:%p thread:%lu lock:%p type: %d", + data, (ulong) data->owner->thread_id, + lock, (int) lock_type)); check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? "enter read_lock" : "enter write_lock", lock_type, 0); if ((int) lock_type <= (int) TL_READ_NO_INSERT) @@ -797,8 +797,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) See Bug#42147 for more information. */ - DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx", - lock->write.data->owner->thread_id)); + DBUG_PRINT("lock",("write locked 1 by thread:%lu", + (ulong) lock->write.data->owner->thread_id)); if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || (lock->write.data->type <= TL_WRITE_DELAYED && (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) || @@ -942,8 +942,8 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) ! lock->read_no_write_count) || has_old_lock(lock->write.data, data->owner)) { - DBUG_PRINT("info", ("write_wait.data: 0x%lx old_type: %d", - (ulong) lock->write_wait.data, + DBUG_PRINT("info", ("write_wait.data: %p old_type: %d", + lock->write_wait.data, lock->write.data->type)); (*lock->write.last)=data; /* Add to running fifo */ @@ -956,13 +956,13 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; } - DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx", - lock->write.data->owner->thread_id)); + DBUG_PRINT("lock",("write locked 2 by thread: %lu", + (ulong) lock->write.data->owner->thread_id)); } else { - DBUG_PRINT("info", ("write_wait.data: 0x%lx", - (ulong) lock->write_wait.data)); + DBUG_PRINT("info", ("write_wait.data:%p", + lock->write_wait.data)); if (!lock->write_wait.data) { /* no scheduled write locks */ my_bool concurrent_insert= 0; @@ -992,8 +992,9 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, ulong lock_wait_timeout) goto end; } } - DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d", - lock->read.data->owner->thread_id, data->type)); + DBUG_PRINT("lock",("write locked 3 by thread:%lu type: %d", + (ulong) lock->read.data->owner->thread_id, + data->type)); } #ifdef WITH_WSREP if (wsrep_break_lock(data, &lock->write, &lock->write_wait)) @@ -1057,8 +1058,8 @@ static inline void free_all_read_locks(THR_LOCK *lock, lock->read_no_write_count++; } /* purecov: begin inspected */ - DBUG_PRINT("lock",("giving read lock to thread: 0x%lx", - data->owner->thread_id)); + DBUG_PRINT("lock",("giving read lock to thread: %lu", + (ulong)data->owner->thread_id)); /* purecov: end */ data->cond=0; /* Mark thread free */ mysql_cond_signal(cond); @@ -1076,8 +1077,9 @@ void thr_unlock(THR_LOCK_DATA *data, uint unlock_flags) THR_LOCK *lock=data->lock; enum thr_lock_type lock_type=data->type; DBUG_ENTER("thr_unlock"); - DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) data, data->owner->thread_id, (long) lock)); + DBUG_PRINT("lock",("data: %p thread: %lu lock: %p", + data, (ulong) data->owner->thread_id, + lock)); mysql_mutex_lock(&lock->mutex); check_locks(lock,"start of release lock", lock_type, 0); @@ -1169,8 +1171,8 @@ static void wake_up_waiters(THR_LOCK *lock) (*lock->check_status)(data->status_param)) data->type=TL_WRITE; /* Upgrade lock */ /* purecov: begin inspected */ - DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx", - data->type, data->owner->thread_id)); + DBUG_PRINT("lock",("giving write lock of type %d to thread: %lu", + data->type, (ulong) data->owner->thread_id)); /* purecov: end */ { mysql_cond_t *cond= data->cond; @@ -1278,7 +1280,7 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, { THR_LOCK_DATA **pos, **end, **first_lock; DBUG_ENTER("thr_multi_lock"); - DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count)); + DBUG_PRINT("lock",("data: %p count: %d", data, count)); if (count > 1) sort_locks(data,count); @@ -1286,6 +1288,7 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, DBUG_RETURN(THR_LOCK_SUCCESS); /* lock everything */ + DEBUG_SYNC_C("thr_multi_lock_before_thr_lock"); for (pos=data,end=data+count; pos < end ; pos++) { enum enum_thr_lock_result result= thr_lock(*pos, owner, lock_wait_timeout); @@ -1297,12 +1300,12 @@ thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, (*pos)->type= TL_UNLOCK; DBUG_RETURN(result); } - DEBUG_SYNC_C("thr_multi_lock_after_thr_lock"); #ifdef MAIN - printf("Thread: %s Got lock: 0x%lx type: %d\n",my_thread_name(), - (long) pos[0]->lock, pos[0]->type); fflush(stdout); + printf("Thread: %s Got lock:%p type: %d\n",my_thread_name(), + pos[0]->lock, pos[0]->type); fflush(stdout); #endif } + DEBUG_SYNC_C("thr_multi_lock_after_thr_lock"); /* Call start_trans for all locks. @@ -1398,23 +1401,23 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count, uint unlock_flags) { THR_LOCK_DATA **pos,**end; DBUG_ENTER("thr_multi_unlock"); - DBUG_PRINT("lock",("data: 0x%lx count: %d flags: %u", (long) data, count, + DBUG_PRINT("lock",("data: %p count: %d flags: %u", data, count, unlock_flags)); for (pos=data,end=data+count; pos < end ; pos++) { #ifdef MAIN - printf("Thread: %s Rel lock: 0x%lx type: %d\n", - my_thread_name(), (long) pos[0]->lock, pos[0]->type); + printf("Thread: %s Rel lock: %p type: %d\n", + my_thread_name(), pos[0]->lock, pos[0]->type); fflush(stdout); #endif if ((*pos)->type != TL_UNLOCK) thr_unlock(*pos, unlock_flags); else { - DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) *pos, (*pos)->owner->thread_id, - (long) (*pos)->lock)); + DBUG_PRINT("lock",("Free lock: data: %p thread:%lu lock: %p", + *pos, (ulong) (*pos)->owner->thread_id, + (*pos)->lock)); } } DBUG_VOID_RETURN; @@ -1662,7 +1665,7 @@ static void thr_print_lock(const char* name,struct st_lock_list *list) prev= &list->data; for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) { - printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->thread_id, + printf("%p (%lu:%d); ", data, (ulong) data->owner->thread_id, (int) data->type); if (data->prev != prev) printf("\nWarning: prev didn't point at previous lock\n"); @@ -1686,7 +1689,7 @@ void thr_print_locks(void) { THR_LOCK *lock=(THR_LOCK*) list->data; mysql_mutex_lock(&lock->mutex); - printf("lock: 0x%lx:",(ulong) lock); + printf("lock:%p:", lock); if ((lock->write_wait.data || lock->read_wait.data) && (! lock->read.data && ! lock->write.data)) printf(" WARNING: "); @@ -1803,7 +1806,7 @@ static void *test_thread(void *arg) printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout); - thr_lock_info_init(&lock_info); + thr_lock_info_init(&lock_info, 0); for (i=0; i < lock_counts[param] ; i++) thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL); for (j=1 ; j < 10 ; j++) /* try locking 10 times */ diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 6010c3ca61a..f6971c890bd 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -105,8 +105,6 @@ void my_mutex_init() #if defined(SAFE_MUTEX_DEFINED) safe_mutex_global_init(); -#elif defined(MY_PTHREAD_FASTMUTEX) - fastmutex_global_init(); #endif } @@ -512,7 +510,7 @@ int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, fprintf(stderr, "safe_mutex: Count was %d in thread 0x%lx when locking mutex %s " "at %s, line %d\n", - mp->count-1, my_thread_dbug_id(), mp->name, file, line); + mp->count-1, (ulong) my_thread_dbug_id(), mp->name, file, line); fflush(stderr); abort(); } @@ -566,7 +564,7 @@ int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, fprintf(stderr, "safe_mutex: Count was %d in thread 0x%lx when locking mutex " "%s at %s, line %d (error: %d (%d))\n", - mp->count-1, my_thread_dbug_id(), mp->name, file, line, + mp->count-1, (ulong) my_thread_dbug_id(), mp->name, file, line, error, error); fflush(stderr); abort(); @@ -838,88 +836,4 @@ static void print_deadlock_warning(safe_mutex_t *new_mutex, DBUG_VOID_RETURN; } -#elif defined(MY_PTHREAD_FASTMUTEX) /* !SAFE_MUTEX_DEFINED */ - -static ulong mutex_delay(ulong delayloops) -{ - ulong i; - volatile ulong j; - - j = 0; - - for (i = 0; i < delayloops * 50; i++) - j += i; - - return(j); -} - -#define MY_PTHREAD_FASTMUTEX_SPINS 8 -#define MY_PTHREAD_FASTMUTEX_DELAY 4 - -static int cpu_count= 0; - -int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, - const pthread_mutexattr_t *attr) -{ - if ((cpu_count > 1) && (attr == MY_MUTEX_INIT_FAST)) - mp->spins= MY_PTHREAD_FASTMUTEX_SPINS; - else - mp->spins= 0; - mp->rng_state= 1; - return pthread_mutex_init(&mp->mutex, attr); -} - -/** - Park-Miller random number generator. A simple linear congruential - generator that operates in multiplicative group of integers modulo n. - - x_{k+1} = (x_k g) mod n - - Popular pair of parameters: n = 2^32 − 5 = 4294967291 and g = 279470273. - The period of the generator is about 2^31. - Largest value that can be returned: 2147483646 (RAND_MAX) - - Reference: - - S. K. Park and K. W. Miller - "Random number generators: good ones are hard to find" - Commun. ACM, October 1988, Volume 31, No 10, pages 1192-1201. -*/ - -static double park_rng(my_pthread_fastmutex_t *mp) -{ - mp->rng_state= ((my_ulonglong)mp->rng_state * 279470273U) % 4294967291U; - return (mp->rng_state / 2147483647.0); -} - -int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp) -{ - int res; - uint i; - uint maxdelay= MY_PTHREAD_FASTMUTEX_DELAY; - - for (i= 0; i < mp->spins; i++) - { - res= pthread_mutex_trylock(&mp->mutex); - - if (res == 0) - return 0; - - if (res != EBUSY) - return res; - - mutex_delay(maxdelay); - maxdelay += park_rng(mp) * MY_PTHREAD_FASTMUTEX_DELAY + 1; - } - return pthread_mutex_lock(&mp->mutex); -} - - -void fastmutex_global_init(void) -{ -#ifdef _SC_NPROCESSORS_CONF - cpu_count= sysconf(_SC_NPROCESSORS_CONF); #endif -} - -#endif /* defined(MY_PTHREAD_FASTMUTEX) && defined(SAFE_MUTEX_DEFINED) */ diff --git a/mysys/tree.c b/mysys/tree.c index e3e34957401..ccf0aa05509 100644 --- a/mysys/tree.c +++ b/mysys/tree.c @@ -91,7 +91,7 @@ void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, myf my_flags) { DBUG_ENTER("init_tree"); - DBUG_PRINT("enter",("tree: 0x%lx size: %d", (long) tree, size)); + DBUG_PRINT("enter",("tree: %p size: %d", tree, size)); if (default_alloc_size < DEFAULT_ALLOC_SIZE) default_alloc_size= DEFAULT_ALLOC_SIZE; @@ -137,7 +137,7 @@ void init_tree(TREE *tree, size_t default_alloc_size, size_t memory_limit, static void free_tree(TREE *tree, myf free_flags) { DBUG_ENTER("free_tree"); - DBUG_PRINT("enter",("tree: 0x%lx", (long) tree)); + DBUG_PRINT("enter",("tree: %p", tree)); if (tree->root) /* If initialized */ { diff --git a/mysys/typelib.c b/mysys/typelib.c index 3798d970a90..f0037921a87 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -76,7 +76,7 @@ static int find_type_eol(const char **x, const TYPELIB *typelib, uint flags, const char *j; CHARSET_INFO *cs= &my_charset_latin1; DBUG_ENTER("find_type_eol"); - DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", *x, (long) typelib)); + DBUG_PRINT("enter",("x: '%s' lib: %p", *x, typelib)); DBUG_ASSERT(!(flags & ~(FIND_TYPE_NO_PREFIX | FIND_TYPE_COMMA_TERM))); @@ -188,7 +188,7 @@ my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) int find; char *i; DBUG_ENTER("find_set"); - DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) lib)); + DBUG_PRINT("enter",("x: '%s' lib: %p", x, lib)); if (!lib->count) { @@ -387,7 +387,7 @@ my_ulonglong find_set_from_flags(const TYPELIB *lib, uint default_name, continue; err: *err_pos= (char*)start; - *err_len= end - start; + *err_len= (uint)(end - start); break; } } diff --git a/mysys/wqueue.c b/mysys/wqueue.c index 6e4081a26e1..15785048040 100644 --- a/mysys/wqueue.c +++ b/mysys/wqueue.c @@ -224,17 +224,17 @@ void wqueue_add_and_wait(WQUEUE *wqueue, { DBUG_ENTER("wqueue_add_and_wait"); DBUG_PRINT("enter", - ("thread: 0x%lx cond: 0x%lx mutex: 0x%lx", - (ulong) thread, (ulong) &thread->suspend, (ulong) lock)); + ("thread: %p cond: %p mutex: %p", + thread, &thread->suspend, lock)); wqueue_add_to_queue(wqueue, thread); do { - DBUG_PRINT("info", ("wait... cond: 0x%lx mutex: 0x%lx", - (ulong) &thread->suspend, (ulong) lock)); + DBUG_PRINT("info", ("wait... cond: %p mutex: %p", + &thread->suspend, lock)); mysql_cond_wait(&thread->suspend, lock); - DBUG_PRINT("info", ("wait done cond: 0x%lx mutex: 0x%lx next: 0x%lx", - (ulong) &thread->suspend, (ulong) lock, - (ulong) thread->next)); + DBUG_PRINT("info", ("wait done cond: %p mutex: %p next: %p", + &thread->suspend, lock, + thread->next)); } while (thread->next); DBUG_VOID_RETURN; |