diff options
Diffstat (limited to 'mysys')
79 files changed, 2753 insertions, 3021 deletions
diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 77933d57d21..ddbb5f5c328 100755..100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -1,18 +1,3 @@ -# Copyright (C) 2006 MySQL AB -# -# 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 - SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") @@ -24,7 +9,7 @@ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DUSE_TLS") SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DUSE_TLS") -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/mysys ) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/include) ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_modify.c errors.c hash.c list.c md5.c mf_brkhant.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 @@ -35,11 +20,10 @@ ADD_LIBRARY(mysys array.c charset-def.c charset.c checksum.c default.c default_m my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c my_div.c my_error.c my_file.c my_fopen.c my_fstream.c my_gethostbyname.c my_gethwaddr.c my_getopt.c my_getsystime.c my_getwd.c my_handler.c my_init.c - my_lib.c my_lock.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c + my_lib.c my_lock.c my_lockmem.c my_malloc.c my_messnc.c my_mkdir.c my_mmap.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_sleep.c my_static.c my_symlink.c my_symlink2.c my_sync.c my_thr_init.c my_wincond.c my_windac.c my_winsem.c my_winthread.c my_write.c ptr_cmp.c queues.c rijndael.c safemalloc.c sha1.c string.c thr_alarm.c thr_lock.c thr_mutex.c - thr_rwlock.c tree.c typelib.c base64.c my_memmem.c - my_getpagesize.c) + thr_rwlock.c tree.c typelib.c my_vle.c base64.c my_memmem.c my_getpagesize.c) diff --git a/mysys/Makefile.am b/mysys/Makefile.am index 8f810598a47..fd6a0f76332 100644 --- a/mysys/Makefile.am +++ b/mysys/Makefile.am @@ -19,12 +19,8 @@ MYSQLBASEdir= $(prefix) INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \ -I$(top_srcdir)/include -I$(srcdir) pkglib_LIBRARIES = libmysys.a -LDADD = libmysys.a ../dbug/libdbug.a \ - ../strings/libmystrings.a -noinst_HEADERS = mysys_priv.h my_static.h \ - my_os2cond.c my_os2dirsrch.c my_os2dirsrch.h \ - my_os2dlfcn.c my_os2file64.c my_os2mutex.c \ - my_os2thread.c my_os2tls.c +LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a $(top_builddir)/dbug/libdbug.a +noinst_HEADERS = mysys_priv.h my_static.h libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_path.c mf_loadpath.c my_file.c \ my_open.c my_create.c my_dup.c my_seek.c my_read.c \ @@ -34,6 +30,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \ my_malloc.c my_realloc.c my_once.c mulalloc.c \ my_alloc.c safemalloc.c my_new.cc \ + my_vle.c my_atomic.c \ my_fopen.c my_fstream.c my_getsystime.c \ my_error.c errors.c my_div.c my_messnc.c \ mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ @@ -41,15 +38,15 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ mf_pack.c mf_unixpath.c mf_strip.c \ mf_wcomp.c mf_wfile.c my_gethwaddr.c \ mf_qsort.c mf_qsort2.c mf_sort.c \ - ptr_cmp.c mf_radix.c queues.c \ - tree.c list.c hash.c array.c string.c typelib.c \ + ptr_cmp.c mf_radix.c queues.c my_getncpus.c \ + tree.c trie.c list.c hash.c array.c string.c typelib.c \ my_copy.c my_append.c my_lib.c \ my_delete.c my_rename.c my_redel.c \ - my_chsize.c my_lread.c my_lwrite.c my_clock.c \ + my_chsize.c my_clock.c \ my_quick.c my_lockmem.c my_static.c \ my_sync.c my_getopt.c my_mkdir.c \ default_modify.c default.c \ - my_compress.c checksum.c raid.cc \ + my_compress.c checksum.c \ my_net.c my_semaphore.c my_port.c my_sleep.c \ charset.c charset-def.c my_bitmap.c my_bit.c md5.c \ my_gethostbyname.c rijndael.c my_aes.c sha1.c \ @@ -57,14 +54,14 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \ my_memmem.c \ my_windac.c my_access.c base64.c my_libwrap.c EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \ - thr_mutex.c thr_rwlock.c mf_soundex.c my_conio.c \ - my_wincond.c my_winsem.c my_winthread.c CMakeLists.txt + thr_mutex.c thr_rwlock.c \ + CMakeLists.txt mf_soundex.c \ + my_conio.c my_wincond.c my_winsem.c my_winthread.c libmysys_a_LIBADD = @THREAD_LOBJECTS@ # test_dir_DEPENDENCIES= $(LIBRARIES) # testhash_DEPENDENCIES= $(LIBRARIES) # test_charset_DEPENDENCIES= $(LIBRARIES) # charset2html_DEPENDENCIES= $(LIBRARIES) -EXTRA_PROGRAMS = DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \ -DDATADIR="\"$(MYSQLDATAdir)\"" \ -DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \ @@ -84,6 +81,12 @@ FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @NOINST_LDFLAGS@ # which automaticly removes the object files you use to compile a final program # +test_bitmap$(EXEEXT): my_bitmap.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN ./my_bitmap.c $(LDADD) $(LIBS) + +test_priority_queue$(EXEEXT): queues.c $(LIBRARIES) + $(LINK) $(FLAGS) -DMAIN ./queues.c $(LDADD) $(LIBS) + test_thr_alarm$(EXEEXT): thr_alarm.c $(LIBRARIES) $(CP) $(srcdir)/thr_alarm.c ./test_thr_alarm.c $(LINK) $(FLAGS) -DMAIN ./test_thr_alarm.c $(LDADD) $(LIBS) diff --git a/mysys/array.c b/mysys/array.c index e3ebe8ddb42..8f4a6087c00 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -277,3 +277,28 @@ void freeze_size(DYNAMIC_ARRAY *array) array->max_element=elements; } } + + +/* + Get the index of a dynamic element + + SYNOPSIS + get_index_dynamic() + array Array + element Whose element index + +*/ + +int get_index_dynamic(DYNAMIC_ARRAY *array, gptr element) +{ + uint ret; + if (array->buffer > element) + return -1; + + ret= (element - array->buffer) / array->size_of_element; + if (ret > array->elements) + return -1; + + return ret; + +} diff --git a/mysys/base64.c b/mysys/base64.c index 6a6b7eae359..9354256f667 100644 --- a/mysys/base64.c +++ b/mysys/base64.c @@ -13,8 +13,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <base64.h> +#include <my_global.h> #include <m_string.h> /* strchr() */ +#include <m_ctype.h> /* my_isspace() */ +#include <base64.h> #ifndef MAIN @@ -114,7 +116,6 @@ pos(unsigned char c) } \ if (i == size) \ { \ - i= size + 1; \ break; \ } \ } @@ -123,44 +124,69 @@ pos(unsigned char c) /* Decode a base64 string - Note: We require that dst is pre-allocated to correct size. - See base64_needed_decoded_length(). + SYNOPSIS + base64_decode() + src Pointer to base64-encoded string + len Length of string at 'src' + dst Pointer to location where decoded data will be stored + end_ptr Pointer to variable that will refer to the character + after the end of the encoded data that were decoded. Can + be NULL. + + DESCRIPTION + + The base64-encoded data in the range ['src','*end_ptr') will be + decoded and stored starting at 'dst'. The decoding will stop + after 'len' characters have been read from 'src', or when padding + occurs in the base64-encoded data. In either case: if 'end_ptr' is + non-null, '*end_ptr' will be set to point to the character after + the last read character, even in the presence of error. + + NOTE + We require that 'dst' is pre-allocated to correct size. - RETURN Number of bytes produced in dst or -1 in case of failure + SEE ALSO + base64_needed_decoded_length(). + + RETURN VALUE + Number of bytes written at 'dst' or -1 in case of failure */ int -base64_decode(const char *src, size_t size, void *dst) +base64_decode(const char *src_base, size_t len, + void *dst, const char **end_ptr) { char b[3]; size_t i= 0; char *dst_base= (char *)dst; + char const *src= src_base; char *d= dst_base; size_t j; - while (i < size) + while (i < len) { unsigned c= 0; size_t mark= 0; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); c += pos(*src++); c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); c += pos(*src++); c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); - if (* src != '=') + if (*src != '=') c += pos(*src++); else { - i= size; + src += 2; /* There should be two bytes padding */ + i= len; mark= 2; c <<= 6; goto end; @@ -168,13 +194,14 @@ base64_decode(const char *src, size_t size, void *dst) c <<= 6; i++; - SKIP_SPACE(src, i, size); + SKIP_SPACE(src, i, len); if (*src != '=') c += pos(*src++); else { - i= size; + src += 1; /* There should be one byte padding */ + i= len; mark= 1; goto end; } @@ -189,11 +216,14 @@ base64_decode(const char *src, size_t size, void *dst) *d++= b[j]; } - if (i != size) - { - return -1; - } - return d - dst_base; + if (end_ptr != NULL) + *end_ptr= src; + + /* + The variable 'i' is set to 'len' when padding has been read, so it + does not actually reflect the number of bytes read from 'src'. + */ + return i != len ? -1 : d - dst_base; } diff --git a/mysys/charset-def.c b/mysys/charset-def.c index 394fe6de1f3..71833550ff4 100644 --- a/mysys/charset-def.c +++ b/mysys/charset-def.c @@ -77,6 +77,7 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused))) CHARSET_INFO *cs; add_compiled_collation(&my_charset_bin); + add_compiled_collation(&my_charset_filename); add_compiled_collation(&my_charset_latin1); add_compiled_collation(&my_charset_latin1_bin); diff --git a/mysys/default.c b/mysys/default.c index 97c52d01031..b68ff8e1779 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -243,7 +243,8 @@ err: handle_option_ctx structure. group_name The name of the group the option belongs to. option The very option to be processed. It is already - prepared to be used in argv (has -- prefix) + prepared to be used in argv (has -- prefix). If it + is NULL, we are handling a new group (section). DESCRIPTION This handler checks whether a group is one of the listed and adds an option @@ -262,6 +263,9 @@ static int handle_default_option(void *in_ctx, const char *group_name, char *tmp; struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx; + if (!option) + return 0; + if (find_type((char *)group_name, ctx->group, 3)) { if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1))) @@ -600,7 +604,7 @@ static int search_default_file_with_ext(Process_option_func opt_handler, strmov(name,config_file); } fn_format(name,name,"","",4); -#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(__WIN__) && !defined(__NETWARE__) { MY_STAT stat_info; if (!my_stat(name,&stat_info,MYF(0))) @@ -718,6 +722,10 @@ static int search_default_file_with_ext(Process_option_func opt_handler, end[0]=0; strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096)); + + /* signal that a new group is found */ + opt_handler(handler_ctx, curr_gr, NULL); + continue; } if (!found_group) @@ -1002,10 +1010,6 @@ static void init_default_directories() #elif defined(__NETWARE__) *ptr++= "sys:/etc/"; #else -#if defined(__EMX__) || defined(OS2) - if ((env= getenv("ETC"))) - *ptr++= env; -#endif *ptr++= "/etc/"; #endif if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) diff --git a/mysys/default_modify.c b/mysys/default_modify.c index be40d3b3660..f58d3e0da86 100644 --- a/mysys/default_modify.c +++ b/mysys/default_modify.c @@ -39,11 +39,13 @@ static char *add_option(char *dst, const char *option_value, SYNOPSYS modify_defaults_file() file_location The location of configuration file to edit - option option to look for - option value The value of the option we would like to set - section_name the name of the section - remove_option This is true if we want to remove the option. - False otherwise. + option The name of the option to look for (can be NULL) + option value The value of the option we would like to set (can be NULL) + section_name The name of the section (must be NOT NULL) + remove_option This defines what we want to remove: + - MY_REMOVE_NONE -- nothing to remove; + - MY_REMOVE_OPTION -- remove the specified option; + - MY_REMOVE_SECTION -- remove the specified section; IMPLEMENTATION We open the option file first, then read the file line-by-line, looking for the section we need. At the same time we put these lines @@ -66,7 +68,9 @@ int modify_defaults_file(const char *file_location, const char *option, FILE *cnf_file; MY_STAT file_stat; char linebuff[BUFF_SIZE], *src_ptr, *dst_ptr, *file_buffer; - uint opt_len, optval_len, sect_len, nr_newlines= 0, buffer_size; + uint opt_len= 0; + uint optval_len= 0; + uint sect_len, nr_newlines= 0, buffer_size; my_bool in_section= FALSE, opt_applied= 0; uint reserve_extended; uint new_opt_len; @@ -80,8 +84,11 @@ int modify_defaults_file(const char *file_location, const char *option, if (my_fstat(fileno(cnf_file), &file_stat, MYF(0))) goto malloc_err; - opt_len= (uint) strlen(option); - optval_len= (uint) strlen(option_value); + if (option && option_value) + { + opt_len= (uint) strlen(option); + optval_len= (uint) strlen(option_value); + } new_opt_len= opt_len + 1 + optval_len + NEWLINE_LEN; @@ -118,8 +125,8 @@ int modify_defaults_file(const char *file_location, const char *option, continue; } - /* correct the option */ - if (in_section && !strncmp(src_ptr, option, opt_len) && + /* correct the option (if requested) */ + if (option && in_section && !strncmp(src_ptr, option, opt_len) && (*(src_ptr + opt_len) == '=' || my_isspace(&my_charset_latin1, *(src_ptr + opt_len)) || *(src_ptr + opt_len) == '\0')) @@ -142,7 +149,12 @@ int modify_defaults_file(const char *file_location, const char *option, } else { - /* If going to new group and we have option to apply, do it now */ + /* + If we are going to the new group and have an option to apply, do + it now. If we are removing a single option or the whole section + this will only trigger opt_applied flag. + */ + if (in_section && !opt_applied && *src_ptr == '[') { dst_ptr= add_option(dst_ptr, option_value, option, remove_option); @@ -152,7 +164,10 @@ int modify_defaults_file(const char *file_location, const char *option, for (; nr_newlines; nr_newlines--) dst_ptr= strmov(dst_ptr, NEWLINE); - dst_ptr= strmov(dst_ptr, linebuff); + + /* Skip the section if MY_REMOVE_SECTION was given */ + if (!in_section || remove_option != MY_REMOVE_SECTION) + dst_ptr= strmov(dst_ptr, linebuff); } /* Look for a section */ if (*src_ptr == '[') @@ -166,18 +181,31 @@ int modify_defaults_file(const char *file_location, const char *option, {} if (*src_ptr != ']') + { + in_section= FALSE; continue; /* Missing closing parenthesis. Assume this was no group */ + } + + if (remove_option == MY_REMOVE_SECTION) + dst_ptr= dst_ptr - strlen(linebuff); + in_section= TRUE; } else in_section= FALSE; /* mark that this section is of no interest to us */ } } - /* File ended. */ - if (!opt_applied && !remove_option && in_section) + + /* + File ended. Apply an option or set opt_applied flag (in case of + MY_REMOVE_SECTION) so that the changes are saved. Do not do anything + if we are removing non-existent option. + */ + + if (!opt_applied && in_section && (remove_option != MY_REMOVE_OPTION)) { /* New option still remains to apply at the end */ - if (*(dst_ptr - 1) != '\n') + if (!remove_option && *(dst_ptr - 1) != '\n') dst_ptr= strmov(dst_ptr, NEWLINE); dst_ptr= add_option(dst_ptr, option_value, option, remove_option); opt_applied= 1; diff --git a/mysys/errors.c b/mysys/errors.c index 857de1325d4..889cf6d7fe3 100644 --- a/mysys/errors.c +++ b/mysys/errors.c @@ -38,7 +38,7 @@ const char * NEAR globerrs[GLOBERRS]= "Can't get working dirctory (Errcode: %d)", "Can't change dir to '%s' (Errcode: %d)", "Warning: '%s' had %d links", - "%d files and %d streams is left open\n", + "Warning: %d files and %d streams is left open\n", "Disk is full writing '%s' (Errcode: %d). Waiting for someone to free space... Retry in %d secs", "Can't create directory '%s' (Errcode: %d)", "Character set '%s' is not a compiled character set and is not specified in the '%s' file", @@ -49,6 +49,7 @@ const char * NEAR globerrs[GLOBERRS]= "Can't sync file '%s' to disk (Errcode: %d)", "Collation '%s' is not a compiled collation and is not specified in the '%s' file", "File '%s' not found (Errcode: %d)", + "File '%s' (fileno: %d) was not closed" }; void init_glob_errs(void) @@ -77,7 +78,7 @@ void init_glob_errs() EE(EE_GETWD) = "Can't get working dirctory (Errcode: %d)"; EE(EE_SETWD) = "Can't change dir to '%s' (Errcode: %d)"; EE(EE_LINK_WARNING) = "Warning: '%s' had %d links"; - EE(EE_OPEN_WARNING) = "%d files and %d streams is left open\n"; + EE(EE_OPEN_WARNING) = "Warning: %d files and %d streams is left open\n"; EE(EE_DISK_FULL) = "Disk is full writing '%s'. Waiting for someone to free space..."; EE(EE_CANT_MKDIR) ="Can't create directory '%s' (Errcode: %d)"; EE(EE_UNKNOWN_CHARSET)= "Character set '%s' is not a compiled character set and is not specified in the %s file"; @@ -88,5 +89,6 @@ void init_glob_errs() EE(EE_SYNC)= "Can't sync file '%s' to disk (Errcode: %d)"; EE(EE_UNKNOWN_COLLATION)= "Collation '%s' is not a compiled collation and is not specified in the %s file"; EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)"; + EE(EE_FILE_NOT_CLOSED) = "File '%s' (fileno: %d) was not closed"; } #endif diff --git a/mysys/hash.c b/mysys/hash.c index 0c949b3a0d8..60168e01e20 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -108,7 +108,7 @@ static inline void hash_free_elements(HASH *hash) void hash_free(HASH *hash) { DBUG_ENTER("hash_free"); - DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash)); + DBUG_PRINT("enter",("hash: 0x%lx", (long) hash)); hash_free_elements(hash); hash->free= 0; diff --git a/mysys/make-ccc b/mysys/make-ccc index 9c54185682a..b34bd80e1d1 100755 --- a/mysys/make-ccc +++ b/mysys/make-ccc @@ -1,4 +1,4 @@ rm -f .deps/* raid.o mf_iocache.o libmysys.a -ccc -DDEFAULT_BASEDIR="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DHAVE_CONFIG_H -I./../include -I../include -I.. -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c array.c checksum.c default.c errors.c getopt.c getopt1.c getvar.c hash.c list.c mf_brkhant.c mf_cache.c mf_casecnv.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_keycache.c mf_loadpath.c mf_pack.c mf_pack2.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_reccache.c mf_same.c mf_sort.c mf_soundex.c mf_stripp.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_alarm.c my_alloc.c my_append.c my_chsize.c my_clock.c my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_fopen.c my_fstream.c my_getwd.c my_init.c my_lib.c my_lockmem.c my_lread.c my_lwrite.c my_malloc.c my_messnc.c my_mkdir.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_static.c my_tempnam.c my_thr_init.c my_write.c ptr_cmp.c queues.c safemalloc.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c +ccc -DDEFAULT_BASEDIR="\"/usr/local/mysql\"" -DDATADIR="\"/usr/local/mysql/var\"" -DHAVE_CONFIG_H -I./../include -I../include -I.. -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c array.c checksum.c default.c errors.c getopt.c getopt1.c getvar.c hash.c list.c mf_brkhant.c mf_cache.c mf_casecnv.c mf_dirname.c mf_fn_ext.c mf_format.c mf_getdate.c mf_keycache.c mf_loadpath.c mf_pack.c mf_pack2.c mf_path.c mf_qsort.c mf_qsort2.c mf_radix.c mf_reccache.c mf_same.c mf_sort.c mf_soundex.c mf_stripp.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_alarm.c my_alloc.c my_append.c my_chsize.c my_clock.c my_compress.c my_copy.c my_create.c my_delete.c my_div.c my_error.c my_fopen.c my_fstream.c my_getwd.c my_init.c my_lib.c my_lockmem.c my_malloc.c my_messnc.c my_mkdir.c my_net.c my_once.c my_open.c my_pread.c my_pthread.c my_quick.c my_read.c my_realloc.c my_redel.c my_rename.c my_seek.c my_static.c my_tempnam.c my_thr_init.c my_write.c ptr_cmp.c queues.c safemalloc.c string.c thr_alarm.c thr_lock.c thr_mutex.c thr_rwlock.c tree.c typelib.c make raid.o mf_iocache.o my_lock.o ar -cr libmysys.a array.o raid.o mf_iocache.o my_lock.o diff --git a/mysys/mf_dirname.c b/mysys/mf_dirname.c index d1672e55b65..87a4a453734 100644 --- a/mysys/mf_dirname.c +++ b/mysys/mf_dirname.c @@ -74,7 +74,7 @@ uint dirname_part(my_string to, const char *name) to Store result here. Must be at least of size min(FN_REFLEN, strlen(from) + 1) to make room for adding FN_LIBCHAR at the end. - from Original filename + from Original filename. May be == to from_end Pointer at end of filename (normally end \0) IMPLEMENTATION @@ -102,6 +102,7 @@ char *convert_dirname(char *to, const char *from, const char *from_end) #ifdef BACKSLASH_MBTAIL CHARSET_INFO *fs= fs_character_set(); #endif + DBUG_ENTER("convert_dirname"); /* We use -2 here, becasue we need place for the last FN_LIBCHAR */ if (!from_end || (from_end - from) > FN_REFLEN-2) @@ -150,5 +151,5 @@ char *convert_dirname(char *to, const char *from, const char *from_end) *to++=FN_LIBCHAR; *to=0; } - return to; /* Pointer to end of dir */ + DBUG_RETURN(to); /* Pointer to end of dir */ } /* convert_dirname */ diff --git a/mysys/mf_format.c b/mysys/mf_format.c index 7a861c9f1e6..3e5eeef6420 100644 --- a/mysys/mf_format.c +++ b/mysys/mf_format.c @@ -53,7 +53,8 @@ my_string fn_format(my_string to, const char *name, const char *dir, if (flag & MY_UNPACK_FILENAME) (void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */ - if ((pos= (char*) strchr(name,FN_EXTCHAR)) != NullS) + if (!(flag & MY_APPEND_EXT) && + (pos= (char*) strchr(name,FN_EXTCHAR)) != NullS) { if ((flag & MY_REPLACE_EXT) == 0) /* If we should keep old ext */ { diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c index 429954a9162..7b3393da4f5 100644 --- a/mysys/mf_iocache2.c +++ b/mysys/mf_iocache2.c @@ -23,6 +23,54 @@ #include <stdarg.h> #include <m_ctype.h> +/* + Copy contents of an IO_CACHE to a file. + + SYNOPSIS + my_b_copy_to_file() + cache IO_CACHE to copy from + file File to copy to + + DESCRIPTION + Copy the contents of the cache to the file. The cache will be + re-inited to a read cache and will read from the beginning of the + cache. + + If a failure to write fully occurs, the cache is only copied + partially. + + TODO + Make this function solid by handling partial reads from the cache + in a correct manner: it should be atomic. + + RETURN VALUE + 0 All OK + 1 An error occured +*/ +int +my_b_copy_to_file(IO_CACHE *cache, FILE *file) +{ + byte buf[IO_SIZE]; + uint bytes_in_cache; + DBUG_ENTER("my_b_copy_to_file"); + + /* Reinit the cache to read from the beginning of the cache */ + if (reinit_io_cache(cache, READ_CACHE, 0L, FALSE, FALSE)) + DBUG_RETURN(1); + bytes_in_cache= my_b_bytes_in_cache(cache); + while (bytes_in_cache > 0) { + uint const read_bytes= min(bytes_in_cache, sizeof(buf)); + DBUG_PRINT("debug", ("Remaining %u bytes - Reading %u bytes", + bytes_in_cache, read_bytes)); + if (my_b_read(cache, buf, read_bytes)) + DBUG_RETURN(1); + if (my_fwrite(file, buf, read_bytes, MYF(MY_WME | MY_NABP)) == (uint) -1) + DBUG_RETURN(1); + bytes_in_cache -= read_bytes; + } + DBUG_RETURN(0); +} + my_off_t my_b_append_tell(IO_CACHE* info) { /* diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 3c4197f847e..ff202e7b313 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -83,14 +83,6 @@ #define KEYCACHE_DEBUG_LOG "my_key_cache_debug.log" */ -#if defined(MSDOS) && !defined(M_IC80386) -/* we nead much memory */ -#undef my_malloc_lock -#undef my_free_lock -#define my_malloc_lock(A,B) halloc((long) (A/IO_SIZE),IO_SIZE) -#define my_free_lock(A,B) hfree(A) -#endif /* defined(MSDOS) && !defined(M_IC80386) */ - #define STRUCT_PTR(TYPE, MEMBER, a) \ (TYPE *) ((char *) (a) - offsetof(TYPE, MEMBER)) @@ -261,15 +253,9 @@ static int keycache_pthread_cond_signal(pthread_cond_t *cond); #define keycache_pthread_cond_signal pthread_cond_signal #endif /* defined(KEYCACHE_DEBUG) */ -static uint next_power(uint value) +static inline uint next_power(uint value) { - uint old_value= 1; - while (value) - { - old_value= value; - value&= value-1; - } - return (old_value << 1); + return (uint) my_round_up_to_next_power((uint32) value) << 1; } @@ -483,8 +469,10 @@ int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, uint age_threshold) { int blocks; +#ifdef THREAD struct st_my_thread_var *thread; KEYCACHE_WQUEUE *wqueue; +#endif DBUG_ENTER("resize_key_cache"); if (!keycache->key_cache_inited) @@ -549,7 +537,7 @@ finish: } #endif keycache_pthread_mutex_unlock(&keycache->cache_lock); - return blocks; + DBUG_RETURN(blocks); } @@ -1115,8 +1103,12 @@ static void unreg_request(KEY_CACHE *keycache, static inline void remove_reader(BLOCK_LINK *block) { +#ifdef THREAD if (! --block->hash_link->requests && block->condvar) keycache_pthread_cond_signal(block->condvar); +#else + --block->hash_link->requests; +#endif } @@ -1125,7 +1117,8 @@ static inline void remove_reader(BLOCK_LINK *block) signals on its termination */ -static inline void wait_for_readers(KEY_CACHE *keycache, BLOCK_LINK *block) +static inline void wait_for_readers(KEY_CACHE *keycache __attribute__((unused)), + BLOCK_LINK *block) { #ifdef THREAD struct st_my_thread_var *thread= my_thread_var; @@ -1222,7 +1215,6 @@ static HASH_LINK *get_hash_link(KEY_CACHE *keycache, int file, my_off_t filepos) { reg1 HASH_LINK *hash_link, **start; - KEYCACHE_PAGE page; #if defined(KEYCACHE_DEBUG) int cnt; #endif @@ -1277,6 +1269,7 @@ restart: #ifdef THREAD /* Wait for a free hash link */ struct st_my_thread_var *thread= my_thread_var; + KEYCACHE_PAGE page; KEYCACHE_DBUG_PRINT("get_hash_link", ("waiting")); page.file= file; page.filepos= filepos; @@ -1601,8 +1594,10 @@ restart: /* Remove the hash link for this page from the hash table */ unlink_hash(keycache, block->hash_link); /* All pending requests for this page must be resubmitted */ +#ifdef THREAD if (block->wqueue[COND_FOR_SAVED].last_thread) release_queue(&block->wqueue[COND_FOR_SAVED]); +#endif } link_to_file_list(keycache, block, file, (my_bool)(block->hash_link ? 1 : 0)); @@ -1682,7 +1677,7 @@ restart: portion is less than read_length, but not less than min_length. */ -static void read_block(KEY_CACHE *keycache, +static void read_block(KEY_CACHE *keycache __attribute__((unused)), BLOCK_LINK *block, uint read_length, uint min_length, my_bool primary) { @@ -1720,8 +1715,10 @@ static void read_block(KEY_CACHE *keycache, KEYCACHE_DBUG_PRINT("read_block", ("primary request: new page in cache")); /* Signal that all pending requests for this page now can be processed */ +#ifdef THREAD if (block->wqueue[COND_FOR_REQUESTED].last_thread) release_queue(&block->wqueue[COND_FOR_REQUESTED]); +#endif } else { @@ -1986,9 +1983,11 @@ int key_cache_insert(KEY_CACHE *keycache, block->length= read_length+offset; KEYCACHE_DBUG_PRINT("key_cache_insert", ("primary request: new page in cache")); +#ifdef THREAD /* Signal that all pending requests for this now can be processed. */ if (block->wqueue[COND_FOR_REQUESTED].last_thread) release_queue(&block->wqueue[COND_FOR_REQUESTED]); +#endif } remove_reader(block); @@ -2232,9 +2231,11 @@ static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) /* Keep track of the number of currently unused blocks. */ keycache->blocks_unused++; +#ifdef THREAD /* All pending requests for this page must be resubmitted. */ if (block->wqueue[COND_FOR_SAVED].last_thread) release_queue(&block->wqueue[COND_FOR_SAVED]); +#endif } @@ -2288,12 +2289,14 @@ static int flush_cached_blocks(KEY_CACHE *keycache, if (!last_errno) last_errno= errno ? errno : -1; } + #ifdef THREAD /* Let to proceed for possible waiting requests to write to the block page. It might happen only during an operation to resize the key cache. */ if (block->wqueue[COND_FOR_SAVED].last_thread) release_queue(&block->wqueue[COND_FOR_SAVED]); +#endif /* type will never be FLUSH_IGNORE_CHANGED here */ if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE)) { diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index d14c24f35d7..1b83c6fda10 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -106,16 +106,27 @@ void pack_dirname(my_string to, const char *from) } /* pack_dirname */ - /* remove unwanted chars from dirname */ - /* if "/../" removes prev dir; "/~/" removes all before ~ */ - /* "//" is same as "/", except on Win32 at start of a file */ - /* "/./" is removed */ - /* Unpacks home_dir if "~/.." used */ - /* Unpacks current dir if if "./.." used */ +/* + remove unwanted chars from dirname -uint cleanup_dirname(register my_string to, const char *from) - /* to may be == from */ + SYNOPSIS + cleanup_dirname() + to Store result here + from Dirname to fix. May be same as to + + IMPLEMENTATION + "/../" removes prev dir + "/~/" removes all before ~ + //" is same as "/", except on Win32 at start of a file + "/./" is removed + Unpacks home_dir if "~/.." used + Unpacks current dir if if "./.." used + RETURN + # length of new name +*/ + +uint cleanup_dirname(register my_string to, const char *from) { reg5 uint length; reg2 my_string pos; diff --git a/mysys/mf_path.c b/mysys/mf_path.c index 9af6173b417..00e6b2046b9 100644 --- a/mysys/mf_path.c +++ b/mysys/mf_path.c @@ -72,7 +72,7 @@ my_string my_path(my_string to, const char *progname, /* test if file without filename is found in path */ /* Returns to if found and to has dirpart if found, else NullS */ -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#if defined(__WIN__) #define F_OK 0 #define PATH_SEP ';' #define PROGRAM_EXTENSION ".exe" diff --git a/mysys/mf_tempdir.c b/mysys/mf_tempdir.c index c24e2a0101b..8d3fc40e96d 100644 --- a/mysys/mf_tempdir.c +++ b/mysys/mf_tempdir.c @@ -16,7 +16,7 @@ #include "mysys_priv.h" #include <m_string.h> -#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(__NETWARE__) #define DELIM ';' #else #define DELIM ':' @@ -27,14 +27,17 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) char *end, *copy; char buff[FN_REFLEN]; DYNAMIC_ARRAY t_arr; + DBUG_ENTER("init_tmpdir"); + DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL")); + pthread_mutex_init(&tmpdir->mutex, MY_MUTEX_INIT_FAST); if (my_init_dynamic_array(&t_arr, sizeof(char*), 1, 5)) - return TRUE; + goto err; if (!pathlist || !pathlist[0]) { /* Get default temporary directory */ pathlist=getenv("TMPDIR"); /* Use this if possible */ -#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) +#if defined( __WIN__) || defined(__NETWARE__) if (!pathlist) pathlist=getenv("TEMP"); if (!pathlist) @@ -45,12 +48,13 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) } do { + uint length; end=strcend(pathlist, DELIM); - convert_dirname(buff, pathlist, end); - if (!(copy=my_strdup(buff, MYF(MY_WME)))) - return TRUE; - if (insert_dynamic(&t_arr, (gptr)©)) - return TRUE; + strmake(buff, pathlist, (uint) (end-pathlist)); + length= cleanup_dirname(buff, buff); + if (!(copy= my_strndup(buff, length, MYF(MY_WME))) || + insert_dynamic(&t_arr, (gptr) ©)) + DBUG_RETURN(TRUE); pathlist=end+1; } while (*end); @@ -58,12 +62,20 @@ my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) tmpdir->list=(char **)t_arr.buffer; tmpdir->max=t_arr.elements-1; tmpdir->cur=0; - return FALSE; + DBUG_RETURN(FALSE); + +err: + delete_dynamic(&t_arr); /* Safe to free */ + pthread_mutex_destroy(&tmpdir->mutex); + DBUG_RETURN(TRUE); } + char *my_tmpdir(MY_TMPDIR *tmpdir) { char *dir; + if (!tmpdir->max) + return tmpdir->list[0]; pthread_mutex_lock(&tmpdir->mutex); dir=tmpdir->list[tmpdir->cur]; tmpdir->cur= (tmpdir->cur == tmpdir->max) ? 0 : tmpdir->cur+1; diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c index 431674c5d61..6c412157937 100644 --- a/mysys/mf_tempfile.c +++ b/mysys/mf_tempfile.c @@ -23,7 +23,7 @@ #endif #ifdef HAVE_TEMPNAM -#if !defined(MSDOS) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(__NETWARE__) extern char **environ; #endif #endif @@ -120,16 +120,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, to[1]= 0; dir=to; } -#ifdef OS2 - /* changing environ variable doesn't work with VACPP */ - char buffer[256], *end; - buffer[sizeof(buffer)-1]= 0; - end= strxnmov(buffer, sizeof(buffer)-1, (char*) "TMP=", dir, NullS); - /* remove ending backslash */ - if (end[-1] == '\\') - end[-1]= 0; - putenv(buffer); -#elif !defined(__NETWARE__) +#if !defined(__NETWARE__) old_env= (char**) environ; if (dir) { /* Don't use TMPDIR if dir is given */ @@ -151,7 +142,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix, { DBUG_PRINT("error",("Got error: %d from tempnam",errno)); } -#if !defined(OS2) && !defined(__NETWARE__) +#if !defined(__NETWARE__) environ=(const char**) old_env; #endif } diff --git a/mysys/my_access.c b/mysys/my_access.c index 9ee20cc942b..210946d50a8 100644 --- a/mysys/my_access.c +++ b/mysys/my_access.c @@ -53,24 +53,111 @@ int my_access(const char *path, int amode) #endif /* __WIN__ */ -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) /* List of file names that causes problem on windows NOTE that one can also not have file names of type CON.TXT + + NOTE: it is important to keep "CLOCK$" on the first place, + we skip it in check_if_legal_tablename. */ - static const char *reserved_names[]= { - "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", - "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", - "LPT7", "LPT8", "LPT9", "CLOCK$", + "CLOCK$", + "CON", "PRN", "AUX", "NUL", + "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", + "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", NullS }; #define MAX_RESERVED_NAME_LENGTH 6 + +/* + Looks up a null-terminated string in a list, + case insensitively. + + SYNOPSIS + str_list_find() + list list of items + str item to find + + RETURN + 0 ok + 1 reserved file name +*/ +static int str_list_find(const char **list, const char *str) +{ + const char **name; + for (name= list; *name; name++) + { + if (!my_strcasecmp(&my_charset_latin1, *name, str)) + return 1; + } + return 0; +} + + +/* + A map for faster reserved_names lookup, + helps to avoid loops in many cases. + 1 - can be the first letter + 2 - can be the second letter + 4 - can be the third letter +*/ +static char reserved_map[256]= +{ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* !"#$%&'()*+,-./ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0123456789:;<=>? */ + 0,1,0,1,0,0,0,0,0,0,0,0,7,4,5,2, /* @ABCDEFGHIJKLMNO */ + 3,0,2,0,4,2,0,0,4,0,0,0,0,0,0,0, /* PQRSTUVWXYZ[\]^_ */ + 0,1,0,1,0,0,0,0,0,0,0,0,7,4,5,2, /* bcdefghijklmno */ + 3,0,2,0,4,2,0,0,4,0,0,0,0,0,0,0, /* pqrstuvwxyz{|}~. */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* ................ */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* ................ */ +}; + + +/* + Check if a table name may cause problems + + SYNOPSIS + check_if_legal_tablename + name Table name (without any extensions) + + DESCRIPTION + We don't check 'CLOCK$' because dollar sign is encoded as @0024, + making table file name 'CLOCK@0024', which is safe. + This is why we start lookup from the second element + (i.e. &reserver_name[1]) + + RETURN + 0 ok + 1 reserved file name +*/ + +int check_if_legal_tablename(const char *name) +{ + DBUG_ENTER("check_if_legal_tablename"); + DBUG_RETURN((reserved_map[(uchar) name[0]] & 1) && + (reserved_map[(uchar) name[1]] & 2) && + (reserved_map[(uchar) name[2]] & 4) && + str_list_find(&reserved_names[1], name)); +} + + +#if defined(__WIN__) || defined(__EMX__) + + /* Check if a path will access a reserverd file name that may cause problems @@ -110,12 +197,5 @@ int check_if_legal_filename(const char *path) } DBUG_RETURN(0); } -#endif - -#ifdef OS2 -int check_if_legal_filename(const char *path) -{ - return 0; -} -#endif /* OS2 */ +#endif /* defined(__WIN__) || defined(__EMX__) */ diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index cfa2dd6216d..5a0ac7b87f7 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -396,6 +396,7 @@ char *strdup_root(MEM_ROOT *root,const char *str) return strmake_root(root, str, (uint) strlen(str)); } + char *strmake_root(MEM_ROOT *root,const char *str, uint len) { char *pos; diff --git a/mysys/my_append.c b/mysys/my_append.c index 274f2110575..ddd3c91e832 100644 --- a/mysys/my_append.c +++ b/mysys/my_append.c @@ -13,7 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" #include <sys/stat.h> #include <m_string.h> diff --git a/mysys/my_atomic.c b/mysys/my_atomic.c new file mode 100644 index 00000000000..6a30267eb80 --- /dev/null +++ b/mysys/my_atomic.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2006 MySQL AB + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <my_global.h> +#include <my_pthread.h> + +#ifndef HAVE_INLINE +/* + the following will cause all inline functions to be instantiated +*/ +#define HAVE_INLINE +#define static extern +#endif + +#include <my_atomic.h> + +/* + checks that the current build of atomic ops + can run on this machine + + RETURN + ATOMIC_xxx values, see my_atomic.h +*/ +int my_atomic_initialize() +{ + DBUG_ASSERT(sizeof(intptr) == sizeof(void *)); + /* currently the only thing worth checking is SMP/UP issue */ +#ifdef MY_ATOMIC_MODE_DUMMY + return my_getncpus() == 1 ? MY_ATOMIC_OK : MY_ATOMIC_NOT_1CPU; +#else + return MY_ATOMIC_OK; +#endif +} + diff --git a/mysys/my_bit.c b/mysys/my_bit.c index 81d63246e7a..5a9b1187c83 100644 --- a/mysys/my_bit.c +++ b/mysys/my_bit.c @@ -75,3 +75,33 @@ uint my_count_bits_ushort(ushort v) return nbits[v]; } + +/* + Next highest power of two + + SYNOPSIS + my_round_up_to_next_power() + v Value to check + + RETURN + Next or equal power of 2 + Note: 0 will return 0 + + NOTES + Algorithm by Sean Anderson, according to: + http://graphics.stanford.edu/~seander/bithacks.html + (Orignal code public domain) + + Comments shows how this works with 01100000000000000000000000001011 +*/ + +uint32 my_round_up_to_next_power(uint32 v) +{ + v--; /* 01100000000000000000000000001010 */ + v|= v >> 1; /* 01110000000000000000000000001111 */ + v|= v >> 2; /* 01111100000000000000000000001111 */ + v|= v >> 4; /* 01111111110000000000000000001111 */ + v|= v >> 8; /* 01111111111111111100000000001111 */ + v|= v >> 16; /* 01111111111111111111111111111111 */ + return v+1; /* 10000000000000000000000000000000 */ +} diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 2cf16111f67..b96bea0ed78 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -19,26 +19,69 @@ API limitations (or, rather asserted safety assumptions, to encourage correct programming) - * the size of the used bitmap is less than ~(uint) 0 - * it's a multiple of 8 (for efficiency reasons) - * when arguments are a bitmap and a bit number, the number - must be within bitmap size - * bitmap_set_prefix() is an exception - one can use ~0 to set all bits - * when both arguments are bitmaps, they must be of the same size - * bitmap_intersect() is an exception :) - (for for Bitmap::intersect(ulonglong map2buff)) - - If THREAD is defined all bitmap operations except bitmap_init/bitmap_free - are thread-safe. + * the internal size is a set of 32 bit words + * the number of bits specified in creation can be any number > 0 + * there are THREAD safe versions of most calls called bitmap_lock_* + many of those are not used and not compiled normally but the code + already exist for them in an #ifdef:ed part. These can only be used + if THREAD was specified in bitmap_init TODO: Make assembler THREAD safe versions of these using test-and-set instructions + + Original version created by Sergei Golubchik 2001 - 2004. + New version written and test program added and some changes to the interface + was made by Mikael Ronström 2005, with assistance of Tomas Ulin and Mats + Kindahl. */ #include "mysys_priv.h" #include <my_bitmap.h> #include <m_string.h> +void create_last_word_mask(MY_BITMAP *map) +{ + /* Get the number of used bits (1..8) in the last byte */ + unsigned int const used= 1U + ((map->n_bits-1U) & 0x7U); + + /* + Create a mask with the upper 'unused' bits set and the lower 'used' + bits clear. The bits within each byte is stored in big-endian order. + */ + unsigned char const mask= (~((1 << used) - 1)) & 255; + + /* + The first bytes are to be set to zero since they represent real bits + in the bitvector. The last bytes are set to 0xFF since they represent + bytes not used by the bitvector. Finally the last byte contains bits + as set by the mask above. + */ + unsigned char *ptr= (unsigned char*)&map->last_word_mask; + + map->last_word_ptr= map->bitmap + no_words_in_map(map)-1; + switch (no_bytes_in_map(map) & 3) { + case 1: + map->last_word_mask= ~0U; + ptr[0]= mask; + return; + case 2: + map->last_word_mask= ~0U; + ptr[0]= 0; + ptr[1]= mask; + return; + case 3: + map->last_word_mask= 0U; + ptr[2]= mask; + ptr[3]= 0xFFU; + return; + case 0: + map->last_word_mask= 0U; + ptr[3]= mask; + return; + } +} + + static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused))) { #ifdef THREAD @@ -56,29 +99,43 @@ static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) } -my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, - my_bool thread_safe) +my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, + my_bool thread_safe __attribute__((unused))) { DBUG_ENTER("bitmap_init"); - - DBUG_ASSERT((bitmap_size & 7) == 0); - bitmap_size/=8; - if (!(map->bitmap=buf) && - !(map->bitmap= (uchar*) my_malloc(bitmap_size + - (thread_safe ? - sizeof(pthread_mutex_t) : 0), - MYF(MY_WME | MY_ZEROFILL)))) - DBUG_RETURN(1); - map->bitmap_size=bitmap_size; -#ifdef THREAD - if (thread_safe) + if (!buf) { - map->mutex=(pthread_mutex_t *)(map->bitmap+bitmap_size); - pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST); + uint size_in_bytes= bitmap_buffer_size(n_bits); + uint extra= 0; +#ifdef THREAD + if (thread_safe) + { + size_in_bytes= ALIGN_SIZE(size_in_bytes); + extra= sizeof(pthread_mutex_t); + } + map->mutex= 0; +#endif + if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME)))) + DBUG_RETURN(1); +#ifdef THREAD + if (thread_safe) + { + map->mutex= (pthread_mutex_t *) ((char*) buf + size_in_bytes); + pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST); + } +#endif } +#ifdef THREAD else - map->mutex=0; + { + DBUG_ASSERT(thread_safe == 0); + } #endif + + map->bitmap= buf; + map->n_bits= n_bits; + create_last_word_mask(map); + bitmap_clear_all(map); DBUG_RETURN(0); } @@ -99,15 +156,6 @@ void bitmap_free(MY_BITMAP *map) } -void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit) -{ - DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); - bitmap_lock(map); - bitmap_fast_set_bit(map, bitmap_bit); - bitmap_unlock(map); -} - - /* test if bit already set and set it if it was not (thread unsafe method) @@ -123,7 +171,7 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) { - uchar *byte= map->bitmap + (bitmap_bit / 8); + uchar *byte= (uchar*)map->bitmap + (bitmap_bit / 8); uchar bit= 1 << ((bitmap_bit) & 7); uchar res= (*byte) & bit; *byte|= bit; @@ -147,182 +195,177 @@ 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->bitmap_size*8); + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); bitmap_lock(map); res= bitmap_fast_test_and_set(map, bitmap_bit); bitmap_unlock(map); return res; } -uint bitmap_set_next(MY_BITMAP *map) -{ - uchar *bitmap=map->bitmap; - uint bit_found = MY_BIT_NONE; - uint bitmap_size=map->bitmap_size; - uint i; +/* + test if bit already set and clear it if it was set(thread unsafe method) - DBUG_ASSERT(map->bitmap); - bitmap_lock(map); - for (i=0; i < bitmap_size ; i++, bitmap++) - { - if (*bitmap != 0xff) - { /* Found slot with free bit */ - uint b; - for (b=0; ; b++) - { - if (!(*bitmap & (1 << b))) - { - *bitmap |= 1<<b; - bit_found = (i*8)+b; - break; - } - } - break; /* Found bit */ - } - } - bitmap_unlock(map); - return bit_found; -} + SYNOPSIS + bitmap_fast_test_and_set() + MAP bit map struct + BIT bit number + RETURN + 0 bit was not set + !=0 bit was set +*/ -void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit) +my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { - DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); - bitmap_lock(map); - bitmap_fast_clear_bit(map, bitmap_bit); - bitmap_unlock(map); + uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8); + uchar bit= 1 << ((bitmap_bit) & 7); + uchar res= (*byte) & bit; + *byte&= ~bit; + return res; } -void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) +my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { - uint prefix_bytes, prefix_bits; - - DBUG_ASSERT(map->bitmap && - (prefix_size <= map->bitmap_size*8 || prefix_size == (uint) ~0)); + my_bool res; + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); bitmap_lock(map); - set_if_smaller(prefix_size, map->bitmap_size*8); - if ((prefix_bytes= prefix_size / 8)) - memset(map->bitmap, 0xff, prefix_bytes); - if ((prefix_bits= prefix_size & 7)) - map->bitmap[prefix_bytes++]= (1 << prefix_bits)-1; - if (prefix_bytes < map->bitmap_size) - bzero(map->bitmap+prefix_bytes, map->bitmap_size-prefix_bytes); + res= bitmap_fast_test_and_clear(map, bitmap_bit); bitmap_unlock(map); + return res; } -void bitmap_clear_all(MY_BITMAP *map) +uint bitmap_set_next(MY_BITMAP *map) { - bitmap_set_prefix(map, 0); + uint bit_found; + DBUG_ASSERT(map->bitmap); + if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE) + bitmap_set_bit(map, bit_found); + return bit_found; } -void bitmap_set_all(MY_BITMAP *map) +void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) { - bitmap_set_prefix(map, ~0); + uint prefix_bytes, prefix_bits, d; + uchar *m= (uchar *)map->bitmap; + + DBUG_ASSERT(map->bitmap && + (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); + m+= prefix_bytes; + if ((prefix_bits= prefix_size & 7)) + *m++= (1 << prefix_bits)-1; + if ((d= no_bytes_in_map(map)-prefix_bytes)) + bzero(m, d); } my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { - uint prefix_bits= prefix_size & 7, res= 0; - uchar *m= map->bitmap, *end_prefix= map->bitmap+prefix_size/8, - *end= map->bitmap+map->bitmap_size; - - DBUG_ASSERT(map->bitmap && prefix_size <= map->bitmap_size*8); + uint prefix_bits= prefix_size & 0x7, res; + uchar *m= (uchar*)map->bitmap; + uchar *end_prefix= m+prefix_size/8; + uchar *end; + DBUG_ASSERT(m && prefix_size <= map->n_bits); + end= m+no_bytes_in_map(map); - bitmap_lock((MY_BITMAP *)map); while (m < end_prefix) if (*m++ != 0xff) - goto ret; + return 0; + *map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/ + res= 0; if (prefix_bits && *m++ != (1 << prefix_bits)-1) goto ret; while (m < end) if (*m++ != 0) goto ret; - - res=1; + res= 1; ret: - bitmap_unlock((MY_BITMAP *)map); - return res; + return res; } -my_bool bitmap_is_clear_all(const MY_BITMAP *map) -{ - return bitmap_is_prefix(map, 0); -} - my_bool bitmap_is_set_all(const MY_BITMAP *map) { - return bitmap_is_prefix(map, map->bitmap_size*8); + my_bitmap_map *data_ptr= map->bitmap; + my_bitmap_map *end= map->last_word_ptr; + *map->last_word_ptr |= map->last_word_mask; + for (; data_ptr <= end; data_ptr++) + if (*data_ptr != 0xFFFFFFFF) + return FALSE; + return TRUE; } -my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit) +my_bool bitmap_is_clear_all(const MY_BITMAP *map) { - DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); - return bitmap_fast_is_set(map, bitmap_bit); + my_bitmap_map *data_ptr= map->bitmap; + my_bitmap_map *end; + if (*map->last_word_ptr & ~map->last_word_mask) + return FALSE; + end= map->last_word_ptr; + for (; data_ptr < end; data_ptr++) + if (*data_ptr) + return FALSE; + return TRUE; } +/* Return TRUE if map1 is a subset of map2 */ my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) { - uint res=0; - uchar *m1=map1->bitmap, *m2=map2->bitmap, *end; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->bitmap_size==map2->bitmap_size); - bitmap_lock((MY_BITMAP *)map1); - bitmap_lock((MY_BITMAP *)map2); - - end= m1+map1->bitmap_size; + map1->n_bits==map2->n_bits); - while (m1 < end) + end= map1->last_word_ptr; + *map1->last_word_ptr &= ~map1->last_word_mask; + *map2->last_word_ptr &= ~map2->last_word_mask; + while (m1 <= end) { if ((*m1++) & ~(*m2++)) - goto ret; + return 0; } - - res=1; -ret: - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock((MY_BITMAP *)map1); - return res; + return 1; } +/* True if bitmaps has any common bits */ -my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) +my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) { - uint res; + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->bitmap_size==map2->bitmap_size); - bitmap_lock((MY_BITMAP *)map1); - bitmap_lock((MY_BITMAP *)map2); + map1->n_bits==map2->n_bits); - res= memcmp(map1->bitmap, map2->bitmap, map1->bitmap_size)==0; - - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock((MY_BITMAP *)map1); - return res; + end= map1->last_word_ptr; + *map1->last_word_ptr &= ~map1->last_word_mask; + *map2->last_word_ptr &= ~map2->last_word_mask; + while (m1 <= end) + { + if ((*m1++) & (*m2++)) + return 1; + } + return 0; } void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) { - uchar *to=map->bitmap, *from=map2->bitmap, *end; - uint len=map->bitmap_size, len2=map2->bitmap_size; + 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); - bitmap_lock(map); - bitmap_lock((MY_BITMAP *)map2); end= to+min(len,len2); - + *map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/ while (to < end) *to++ &= *from++; @@ -332,9 +375,6 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) while (to < end) *to++=0; } - - bitmap_unlock((MY_BITMAP *)map2); - bitmap_unlock(map); } @@ -361,8 +401,8 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) { uchar use_byte= use_bit ? 0xff : 0; - uchar *to= map->bitmap + from_byte; - uchar *end= map->bitmap + map->bitmap_size; + uchar *to= (uchar *)map->bitmap + from_byte; + uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8; while (to < end) *to++= use_byte; @@ -371,37 +411,283 @@ void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) { - uchar *to=map->bitmap, *from=map2->bitmap, *end; + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; + DBUG_ASSERT(map->bitmap && map2->bitmap && + map->n_bits==map2->n_bits); + + end= map->last_word_ptr; + + while (to <= end) + *to++ &= ~(*from++); +} + + +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); + end= map->last_word_ptr; + + while (to <= end) + *to++ |= *from++; +} + + +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); + while (to <= end) + *to++ ^= *from++; +} + + +void bitmap_invert(MY_BITMAP *map) +{ + my_bitmap_map *to= map->bitmap, *end; + + DBUG_ASSERT(map->bitmap); + end= map->last_word_ptr; + + while (to <= end) + *to++ ^= 0xFFFFFFFF; +} + + +uint bitmap_bits_set(const MY_BITMAP *map) +{ + uchar *m= (uchar*)map->bitmap; + uchar *end= m + no_bytes_in_map(map); + uint res= 0; + + DBUG_ASSERT(map->bitmap); + *map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/ + while (m < end) + res+= my_count_bits_ushort(*m++); + return res; +} + + +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->bitmap_size==map2->bitmap_size); + map->n_bits==map2->n_bits); + end= map->last_word_ptr; + while (to <= end) + *to++ = *from++; +} + + +uint bitmap_get_first_set(const MY_BITMAP *map) +{ + uchar *byte_ptr; + uint i,j,k; + my_bitmap_map *data_ptr, *end= map->last_word_ptr; + + DBUG_ASSERT(map->bitmap); + data_ptr= map->bitmap; + *map->last_word_ptr &= ~map->last_word_mask; + + for (i=0; data_ptr <= end; data_ptr++, i++) + { + if (*data_ptr) + { + byte_ptr= (uchar*)data_ptr; + for (j=0; ; j++, byte_ptr++) + { + if (*byte_ptr) + { + for (k=0; ; k++) + { + if (*byte_ptr & (1 << k)) + return (i*32) + (j*8) + k; + } + DBUG_ASSERT(0); + } + } + DBUG_ASSERT(0); + } + } + return MY_BIT_NONE; +} + + +uint bitmap_get_first(const MY_BITMAP *map) +{ + uchar *byte_ptr; + uint i,j,k; + my_bitmap_map *data_ptr, *end= map->last_word_ptr; + + DBUG_ASSERT(map->bitmap); + data_ptr= map->bitmap; + *map->last_word_ptr|= map->last_word_mask; + + for (i=0; data_ptr <= end; data_ptr++, i++) + { + if (*data_ptr != 0xFFFFFFFF) + { + byte_ptr= (uchar*)data_ptr; + for (j=0; ; j++, byte_ptr++) + { + if (*byte_ptr != 0xFF) + { + for (k=0; ; k++) + { + if (!(*byte_ptr & (1 << k))) + return (i*32) + (j*8) + k; + } + DBUG_ASSERT(0); + } + } + DBUG_ASSERT(0); + } + } + return MY_BIT_NONE; +} + + +uint bitmap_lock_set_next(MY_BITMAP *map) +{ + uint bit_found; bitmap_lock(map); - bitmap_lock((MY_BITMAP *)map2); + bit_found= bitmap_set_next(map); + bitmap_unlock(map); + return bit_found; +} - end= to+map->bitmap_size; - while (to < end) - *to++ &= ~(*from++); +void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) +{ + bitmap_lock(map); + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + bitmap_clear_bit(map, bitmap_bit); + bitmap_unlock(map); +} - bitmap_unlock((MY_BITMAP *)map2); + +#ifdef NOT_USED +my_bool bitmap_lock_is_prefix(const MY_BITMAP *map, uint prefix_size) +{ + my_bool res; + bitmap_lock((MY_BITMAP *)map); + res= bitmap_is_prefix(map, prefix_size); + bitmap_unlock((MY_BITMAP *)map); + return res; +} + + +void bitmap_lock_set_all(MY_BITMAP *map) +{ + bitmap_lock(map); + bitmap_set_all(map); bitmap_unlock(map); } -void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) +void bitmap_lock_clear_all(MY_BITMAP *map) { - uchar *to=map->bitmap, *from=map2->bitmap, *end; + bitmap_lock(map); + bitmap_clear_all(map); + bitmap_unlock(map); +} - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->bitmap_size==map2->bitmap_size); + +void bitmap_lock_set_prefix(MY_BITMAP *map, uint prefix_size) +{ bitmap_lock(map); + bitmap_set_prefix(map, prefix_size); + bitmap_unlock(map); +} + + +my_bool bitmap_lock_is_clear_all(const MY_BITMAP *map) +{ + uint res; + bitmap_lock((MY_BITMAP *)map); + res= bitmap_is_clear_all(map); + bitmap_unlock((MY_BITMAP *)map); + return res; +} + + +my_bool bitmap_lock_is_set_all(const MY_BITMAP *map) +{ + uint res; + bitmap_lock((MY_BITMAP *)map); + res= bitmap_is_set_all(map); + bitmap_unlock((MY_BITMAP *)map); + return res; +} + + +my_bool bitmap_lock_is_set(const MY_BITMAP *map, uint bitmap_bit) +{ + my_bool res; + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + bitmap_lock((MY_BITMAP *)map); + res= bitmap_is_set(map, bitmap_bit); + bitmap_unlock((MY_BITMAP *)map); + return res; +} + + +my_bool bitmap_lock_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) +{ + uint res; + bitmap_lock((MY_BITMAP *)map1); bitmap_lock((MY_BITMAP *)map2); + res= bitmap_is_subset(map1, map2); + bitmap_unlock((MY_BITMAP *)map2); + bitmap_unlock((MY_BITMAP *)map1); + return res; +} - end= to+map->bitmap_size; - while (to < end) - *to++ |= *from++; +my_bool bitmap_lock_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) +{ + uint res; + DBUG_ASSERT(map1->bitmap && map2->bitmap && + map1->n_bits==map2->n_bits); + bitmap_lock((MY_BITMAP *)map1); + bitmap_lock((MY_BITMAP *)map2); + res= bitmap_cmp(map1, map2); + bitmap_unlock((MY_BITMAP *)map2); + bitmap_unlock((MY_BITMAP *)map1); + return res; +} + + +void bitmap_lock_intersect(MY_BITMAP *map, const MY_BITMAP *map2) +{ + bitmap_lock(map); + bitmap_lock((MY_BITMAP *)map2); + bitmap_intersect(map, map2); + bitmap_unlock((MY_BITMAP *)map2); + bitmap_unlock(map); +} + + +void bitmap_lock_subtract(MY_BITMAP *map, const MY_BITMAP *map2) +{ + bitmap_lock(map); + bitmap_lock((MY_BITMAP *)map2); + bitmap_subtract(map, map2); + bitmap_unlock((MY_BITMAP *)map2); + bitmap_unlock(map); +} + + +void bitmap_lock_union(MY_BITMAP *map, const MY_BITMAP *map2) +{ + bitmap_lock(map); + bitmap_lock((MY_BITMAP *)map2); + bitmap_union(map, map2); bitmap_unlock((MY_BITMAP *)map2); bitmap_unlock(map); } @@ -414,19 +700,12 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) RETURN Number of set bits in the bitmap. */ - -uint bitmap_bits_set(const MY_BITMAP *map) -{ - uchar *m= map->bitmap; - uchar *end= m + map->bitmap_size; - uint res= 0; - - DBUG_ASSERT(map->bitmap); +uint bitmap_lock_bits_set(const MY_BITMAP *map) +{ + uint res; bitmap_lock((MY_BITMAP *)map); - while (m < end) - { - res+= my_count_bits_ushort(*m++); - } + DBUG_ASSERT(map->bitmap); + res= bitmap_bits_set(map); bitmap_unlock((MY_BITMAP *)map); return res; } @@ -439,33 +718,412 @@ uint bitmap_bits_set(const MY_BITMAP *map) RETURN Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set. */ +uint bitmap_lock_get_first(const MY_BITMAP *map) +{ + uint res; + bitmap_lock((MY_BITMAP*)map); + res= bitmap_get_first(map); + bitmap_unlock((MY_BITMAP*)map); + return res; +} -uint bitmap_get_first(const MY_BITMAP *map) + +uint bitmap_lock_get_first_set(const MY_BITMAP *map) +{ + uint res; + bitmap_lock((MY_BITMAP*)map); + res= bitmap_get_first_set(map); + bitmap_unlock((MY_BITMAP*)map); + return res; +} + + +void bitmap_lock_set_bit(MY_BITMAP *map, uint bitmap_bit) +{ + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + bitmap_lock(map); + bitmap_set_bit(map, bitmap_bit); + bitmap_unlock(map); +} + + +void bitmap_lock_flip_bit(MY_BITMAP *map, uint bitmap_bit) +{ + DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); + bitmap_lock(map); + bitmap_flip_bit(map, bitmap_bit); + bitmap_unlock(map); +} +#endif +#ifdef MAIN + +uint get_rand_bit(uint bitsize) +{ + return (rand() % bitsize); +} + +bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize) +{ + uint i, test_bit; + uint no_loops= bitsize > 128 ? 128 : bitsize; + for (i=0; i < no_loops; i++) + { + test_bit= get_rand_bit(bitsize); + bitmap_set_bit(map, test_bit); + if (!bitmap_is_set(map, test_bit)) + goto error1; + bitmap_clear_bit(map, test_bit); + if (bitmap_is_set(map, test_bit)) + goto error2; + } + return FALSE; +error1: + printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize); + return TRUE; +error2: + printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize); + return TRUE; +} + +bool test_flip_bit(MY_BITMAP *map, uint bitsize) +{ + uint i, test_bit; + uint no_loops= bitsize > 128 ? 128 : bitsize; + for (i=0; i < no_loops; i++) + { + test_bit= get_rand_bit(bitsize); + bitmap_flip_bit(map, test_bit); + if (!bitmap_is_set(map, test_bit)) + goto error1; + bitmap_flip_bit(map, test_bit); + if (bitmap_is_set(map, test_bit)) + goto error2; + } + return FALSE; +error1: + printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize); + return TRUE; +error2: + printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize); + return TRUE; +} + +bool test_operators(MY_BITMAP *map __attribute__((unused)), + uint bitsize __attribute__((unused))) +{ + return FALSE; +} + +bool test_get_all_bits(MY_BITMAP *map, uint bitsize) { - uchar *bitmap=map->bitmap; - uint bit_found = MY_BIT_NONE; - uint bitmap_size=map->bitmap_size; uint i; + bitmap_set_all(map); + if (!bitmap_is_set_all(map)) + goto error1; + if (!bitmap_is_prefix(map, bitsize)) + goto error5; + bitmap_clear_all(map); + if (!bitmap_is_clear_all(map)) + goto error2; + if (!bitmap_is_prefix(map, 0)) + goto error6; + for (i=0; i<bitsize;i++) + bitmap_set_bit(map, i); + if (!bitmap_is_set_all(map)) + goto error3; + for (i=0; i<bitsize;i++) + bitmap_clear_bit(map, i); + if (!bitmap_is_clear_all(map)) + goto error4; + return FALSE; +error1: + printf("Error in set_all, bitsize = %u", bitsize); + return TRUE; +error2: + printf("Error in clear_all, bitsize = %u", bitsize); + return TRUE; +error3: + printf("Error in bitmap_is_set_all, bitsize = %u", bitsize); + return TRUE; +error4: + printf("Error in bitmap_is_clear_all, bitsize = %u", bitsize); + return TRUE; +error5: + printf("Error in set_all through set_prefix, bitsize = %u", bitsize); + return TRUE; +error6: + printf("Error in clear_all through set_prefix, bitsize = %u", bitsize); + return TRUE; +} - DBUG_ASSERT(map->bitmap); - bitmap_lock((MY_BITMAP *)map); - for (i=0; i < bitmap_size ; i++, bitmap++) +bool test_compare_operators(MY_BITMAP *map, uint bitsize) +{ + uint i, j, test_bit1, test_bit2, test_bit3,test_bit4; + uint no_loops= bitsize > 128 ? 128 : bitsize; + MY_BITMAP map2_obj, map3_obj; + MY_BITMAP *map2= &map2_obj, *map3= &map3_obj; + my_bitmap_map map2buf[1024]; + my_bitmap_map map3buf[1024]; + bitmap_init(&map2_obj, map2buf, bitsize, FALSE); + bitmap_init(&map3_obj, map3buf, bitsize, FALSE); + bitmap_clear_all(map2); + bitmap_clear_all(map3); + for (i=0; i < no_loops; i++) { - if (*bitmap != 0xff) - { /* Found slot with free bit */ - uint b; - for (b=0; ; b++) - { - if (!(*bitmap & (1 << b))) - { - bit_found = (i*8)+b; - break; - } - } - break; /* Found bit */ + test_bit1=get_rand_bit(bitsize); + bitmap_set_prefix(map, test_bit1); + test_bit2=get_rand_bit(bitsize); + bitmap_set_prefix(map2, test_bit2); + bitmap_intersect(map, map2); + test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1; + bitmap_set_prefix(map3, test_bit3); + if (!bitmap_cmp(map, map3)) + goto error1; + bitmap_clear_all(map); + bitmap_clear_all(map2); + bitmap_clear_all(map3); + test_bit1=get_rand_bit(bitsize); + test_bit2=get_rand_bit(bitsize); + test_bit3=get_rand_bit(bitsize); + bitmap_set_prefix(map, test_bit1); + bitmap_set_prefix(map2, test_bit2); + test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1; + bitmap_set_prefix(map3, test_bit3); + bitmap_union(map, map2); + if (!bitmap_cmp(map, map3)) + goto error2; + bitmap_clear_all(map); + bitmap_clear_all(map2); + bitmap_clear_all(map3); + test_bit1=get_rand_bit(bitsize); + test_bit2=get_rand_bit(bitsize); + test_bit3=get_rand_bit(bitsize); + bitmap_set_prefix(map, test_bit1); + bitmap_set_prefix(map2, test_bit2); + bitmap_xor(map, map2); + test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1; + test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1; + bitmap_set_prefix(map3, test_bit3); + for (j=0; j < test_bit4; j++) + bitmap_clear_bit(map3, j); + if (!bitmap_cmp(map, map3)) + goto error3; + bitmap_clear_all(map); + bitmap_clear_all(map2); + bitmap_clear_all(map3); + test_bit1=get_rand_bit(bitsize); + test_bit2=get_rand_bit(bitsize); + test_bit3=get_rand_bit(bitsize); + bitmap_set_prefix(map, test_bit1); + bitmap_set_prefix(map2, test_bit2); + bitmap_subtract(map, map2); + if (test_bit2 < test_bit1) + { + bitmap_set_prefix(map3, test_bit1); + for (j=0; j < test_bit2; j++) + bitmap_clear_bit(map3, j); } + if (!bitmap_cmp(map, map3)) + goto error4; + bitmap_clear_all(map); + bitmap_clear_all(map2); + bitmap_clear_all(map3); + test_bit1=get_rand_bit(bitsize); + bitmap_set_prefix(map, test_bit1); + bitmap_invert(map); + bitmap_set_all(map3); + for (j=0; j < test_bit1; j++) + bitmap_clear_bit(map3, j); + if (!bitmap_cmp(map, map3)) + goto error5; + bitmap_clear_all(map); + bitmap_clear_all(map3); } - bitmap_unlock((MY_BITMAP *)map); - return bit_found; + return FALSE; +error1: + printf("intersect error bitsize=%u,size1=%u,size2=%u", bitsize, + test_bit1,test_bit2); + return TRUE; +error2: + printf("union error bitsize=%u,size1=%u,size2=%u", bitsize, + test_bit1,test_bit2); + return TRUE; +error3: + printf("xor error bitsize=%u,size1=%u,size2=%u", bitsize, + test_bit1,test_bit2); + return TRUE; +error4: + printf("subtract error bitsize=%u,size1=%u,size2=%u", bitsize, + test_bit1,test_bit2); + return TRUE; +error5: + printf("invert error bitsize=%u,size=%u", bitsize, + test_bit1); + return TRUE; } +bool test_count_bits_set(MY_BITMAP *map, uint bitsize) +{ + uint i, bit_count=0, test_bit; + uint no_loops= bitsize > 128 ? 128 : bitsize; + for (i=0; i < no_loops; i++) + { + test_bit=get_rand_bit(bitsize); + if (!bitmap_is_set(map, test_bit)) + { + bitmap_set_bit(map, test_bit); + bit_count++; + } + } + if (bit_count==0 && bitsize > 0) + goto error1; + if (bitmap_bits_set(map) != bit_count) + goto error2; + return FALSE; +error1: + printf("No bits set bitsize = %u", bitsize); + return TRUE; +error2: + printf("Wrong count of bits set, bitsize = %u", bitsize); + return TRUE; +} + +bool test_get_first_bit(MY_BITMAP *map, uint bitsize) +{ + uint i, test_bit; + uint no_loops= bitsize > 128 ? 128 : bitsize; + for (i=0; i < no_loops; i++) + { + test_bit=get_rand_bit(bitsize); + bitmap_set_bit(map, test_bit); + if (bitmap_get_first_set(map) != test_bit) + goto error1; + bitmap_set_all(map); + bitmap_clear_bit(map, test_bit); + if (bitmap_get_first(map) != test_bit) + goto error2; + bitmap_clear_all(map); + } + return FALSE; +error1: + printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit); + return TRUE; +error2: + printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit); + return TRUE; +} + +bool test_get_next_bit(MY_BITMAP *map, uint bitsize) +{ + uint i, j, test_bit; + uint no_loops= bitsize > 128 ? 128 : bitsize; + for (i=0; i < no_loops; i++) + { + test_bit=get_rand_bit(bitsize); + for (j=0; j < test_bit; j++) + bitmap_set_next(map); + if (!bitmap_is_prefix(map, test_bit)) + goto error1; + bitmap_clear_all(map); + } + return FALSE; +error1: + printf("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit); + return TRUE; +} + +bool test_prefix(MY_BITMAP *map, uint bitsize) +{ + uint i, j, test_bit; + uint no_loops= bitsize > 128 ? 128 : bitsize; + for (i=0; i < no_loops; i++) + { + test_bit=get_rand_bit(bitsize); + bitmap_set_prefix(map, test_bit); + if (!bitmap_is_prefix(map, test_bit)) + goto error1; + bitmap_clear_all(map); + for (j=0; j < test_bit; j++) + bitmap_set_bit(map, j); + if (!bitmap_is_prefix(map, test_bit)) + goto error2; + bitmap_set_all(map); + for (j=bitsize - 1; ~(j-test_bit); j--) + bitmap_clear_bit(map, j); + if (!bitmap_is_prefix(map, test_bit)) + goto error3; + bitmap_clear_all(map); + } + return FALSE; +error1: + printf("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit); + return TRUE; +error2: + printf("prefix2 error bitsize = %u, prefix_size = %u", bitsize,test_bit); + return TRUE; +error3: + printf("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit); + return TRUE; +} + + +bool do_test(uint bitsize) +{ + MY_BITMAP map; + my_bitmap_map buf[1024]; + if (bitmap_init(&map, buf, bitsize, FALSE)) + { + printf("init error for bitsize %d", bitsize); + goto error; + } + if (test_set_get_clear_bit(&map,bitsize)) + goto error; + bitmap_clear_all(&map); + if (test_flip_bit(&map,bitsize)) + goto error; + bitmap_clear_all(&map); + if (test_operators(&map,bitsize)) + goto error; + bitmap_clear_all(&map); + if (test_get_all_bits(&map, bitsize)) + goto error; + bitmap_clear_all(&map); + if (test_compare_operators(&map,bitsize)) + goto error; + bitmap_clear_all(&map); + if (test_count_bits_set(&map,bitsize)) + goto error; + bitmap_clear_all(&map); + if (test_get_first_bit(&map,bitsize)) + goto error; + bitmap_clear_all(&map); + if (test_get_next_bit(&map,bitsize)) + goto error; + if (test_prefix(&map,bitsize)) + goto error; + return FALSE; +error: + printf("\n"); + return TRUE; +} + +int main() +{ + int i; + for (i= 1; i < 4096; i++) + { + printf("Start test for bitsize=%u\n",i); + if (do_test(i)) + return -1; + } + printf("OK\n"); + return 0; +} + +/* + In directory mysys: + make test_bitmap + will build the bitmap tests and ./test_bitmap will execute it +*/ + +#endif diff --git a/mysys/my_clock.c b/mysys/my_clock.c index c5fa516a622..adc755028d5 100644 --- a/mysys/my_clock.c +++ b/mysys/my_clock.c @@ -13,17 +13,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "my_global.h" -#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__NETWARE__) #include "mysys_priv.h" #include <sys/times.h> #endif long my_clock(void) { -#if !defined(MSDOS) && !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(__WIN__) && !defined(__NETWARE__) struct tms tmsbuf; VOID(times(&tmsbuf)); return (tmsbuf.tms_utime + tmsbuf.tms_stime); diff --git a/mysys/my_compress.c b/mysys/my_compress.c index c054bf155b1..45e60552592 100644 --- a/mysys/my_compress.c +++ b/mysys/my_compress.c @@ -94,4 +94,133 @@ my_bool my_uncompress (byte *packet, ulong *len, ulong *complen) } DBUG_RETURN(0); } + +/* + Internal representation of the frm blob +*/ + +struct frm_blob_header +{ + uint ver; /* Version of header */ + uint orglen; /* Original length of compressed data */ + uint complen; /* Compressed length of data, 0=uncompressed */ +}; + +struct frm_blob_struct +{ + struct frm_blob_header head; + char data[1]; +}; + +/* + packfrm is a method used to compress the frm file for storage in a + handler. This method was developed for the NDB handler and has been moved + here to serve also other uses. + + SYNOPSIS + packfrm() + data Data reference to frm file data + len Length of frm file data + out:pack_data Reference to the pointer to the packed frm data + out:pack_len Length of packed frm file data + + RETURN VALUES + 0 Success + >0 Failure +*/ + +int packfrm(const void *data, uint len, + const void **pack_data, uint *pack_len) +{ + int error; + ulong org_len, comp_len; + uint blob_len; + struct frm_blob_struct *blob; + DBUG_ENTER("packfrm"); + DBUG_PRINT("enter", ("data: 0x%lx, len: %d", (long) data, len)); + + error= 1; + org_len= len; + if (my_compress((byte*)data, &org_len, &comp_len)) + goto err; + + DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", org_len, comp_len)); + DBUG_DUMP("compressed", (char*)data, org_len); + + error= 2; + blob_len= sizeof(struct frm_blob_header)+org_len; + if (!(blob= (struct frm_blob_struct*) my_malloc(blob_len,MYF(MY_WME)))) + goto err; + + /* Store compressed blob in machine independent format */ + int4store((char*)(&blob->head.ver), 1); + int4store((char*)(&blob->head.orglen), comp_len); + int4store((char*)(&blob->head.complen), org_len); + + /* Copy frm data into blob, already in machine independent format */ + memcpy(blob->data, data, org_len); + + *pack_data= blob; + *pack_len= blob_len; + error= 0; + + DBUG_PRINT("exit", ("pack_data: 0x%lx pack_len: %d", + (long) *pack_data, *pack_len)); +err: + DBUG_RETURN(error); + +} + +/* + unpackfrm is a method used to decompress the frm file received from a + handler. This method was developed for the NDB handler and has been moved + here to serve also other uses for other clustered storage engines. + + SYNOPSIS + unpackfrm() + pack_data Data reference to packed frm file data + out:unpack_data Reference to the pointer to the unpacked frm data + out:unpack_len Length of unpacked frm file data + + RETURN VALUES¨ + 0 Success + >0 Failure +*/ + +int unpackfrm(const void **unpack_data, uint *unpack_len, + const void *pack_data) +{ + const struct frm_blob_struct *blob= (struct frm_blob_struct*)pack_data; + byte *data; + ulong complen, orglen, ver; + DBUG_ENTER("unpackfrm"); + DBUG_PRINT("enter", ("pack_data: 0x%lx", (long) pack_data)); + + complen= uint4korr((char*)&blob->head.complen); + orglen= uint4korr((char*)&blob->head.orglen); + ver= uint4korr((char*)&blob->head.ver); + + DBUG_PRINT("blob",("ver: %lu complen: %lu orglen: %lu", + ver,complen,orglen)); + DBUG_DUMP("blob->data", (char*) blob->data, complen); + + if (ver != 1) + DBUG_RETURN(1); + if (!(data= my_malloc(max(orglen, complen), MYF(MY_WME)))) + DBUG_RETURN(2); + memcpy(data, blob->data, complen); + + + if (my_uncompress(data, &complen, &orglen)) + { + my_free((char*)data, MYF(0)); + DBUG_RETURN(3); + } + + *unpack_data= data; + *unpack_len= complen; + + DBUG_PRINT("exit", ("frmdata: 0x%lx len: %d", (long) *unpack_data, *unpack_len)); + DBUG_RETURN(0); +} #endif /* HAVE_COMPRESS */ diff --git a/mysys/my_copy.c b/mysys/my_copy.c index 6143700befc..80a68f61b12 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -13,7 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" #include <my_dir.h> /* for stat */ #include <m_string.h> @@ -94,7 +93,7 @@ int my_copy(const char *from, const char *to, myf MyFlags) if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat) DBUG_RETURN(0); /* File copyed but not stat */ VOID(chmod(to, stat_buff.st_mode & 07777)); /* Copy modes */ -#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(__WIN__) && !defined(__NETWARE__) VOID(chown(to, stat_buff.st_uid,stat_buff.st_gid)); /* Copy ownership */ #endif #if !defined(VMS) && !defined(__ZTC__) diff --git a/mysys/my_create.c b/mysys/my_create.c index d612926c1a5..5639459f5a9 100644 --- a/mysys/my_create.c +++ b/mysys/my_create.c @@ -13,12 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "mysys_priv.h" #include <my_dir.h> #include "mysys_err.h" #include <errno.h> -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#if defined(__WIN__) #include <share.h> #endif @@ -40,19 +39,12 @@ File my_create(const char *FileName, int CreateFlags, int access_flags, DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %d", FileName, CreateFlags, access_flags, MyFlags)); -#if !defined(NO_OPEN_3) && !defined(__EMX__) +#if !defined(NO_OPEN_3) fd = open((my_string) FileName, access_flags | O_CREAT, CreateFlags ? CreateFlags : my_umask); #elif defined(VMS) fd = open((my_string) FileName, access_flags | O_CREAT, 0, "ctx=stm","ctx=bin"); -#elif defined(MSDOS) || defined(__EMX__) || defined(OS2) - if (access_flags & O_SHARE) - fd = sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, - SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); - else - fd = open((my_string) FileName, access_flags | O_CREAT | O_BINARY, - MY_S_IREAD | MY_S_IWRITE); #elif defined(__WIN__) fd= my_sopen((my_string) FileName, access_flags | O_CREAT | O_BINARY, SH_DENYNO, MY_S_IREAD | MY_S_IWRITE); diff --git a/mysys/my_dup.c b/mysys/my_dup.c index 2c6a42726e4..55f5e0c0099 100644 --- a/mysys/my_dup.c +++ b/mysys/my_dup.c @@ -13,12 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "mysys_priv.h" #include "mysys_err.h" #include <my_dir.h> #include <errno.h> -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) +#if defined(__WIN__) #include <share.h> #endif diff --git a/mysys/my_error.c b/mysys/my_error.c index 836f851322b..48392fe84c3 100644 --- a/mysys/my_error.c +++ b/mysys/my_error.c @@ -52,8 +52,10 @@ static struct my_err_head int meh_first; /* error number matching array slot 0 */ int meh_last; /* error number matching last slot */ } my_errmsgs_globerrs = {NULL, globerrs, EE_ERROR_FIRST, EE_ERROR_LAST}; + static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs; + /* Error message to user @@ -75,7 +77,6 @@ int my_error(int nr, myf MyFlags, ...) va_list args; char ebuff[ERRMSGSIZE + 20]; DBUG_ENTER("my_error"); - DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno)); /* Search for the error messages array, which could contain the message. */ @@ -101,6 +102,7 @@ int my_error(int nr, myf MyFlags, ...) DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags)); } + /* Error as printf @@ -249,3 +251,15 @@ const char **my_error_unregister(int first, int last) return errmsgs; } + + +void my_error_unregister_all(void) +{ + struct my_err_head *list, *next; + for (list= my_errmsgs_globerrs.meh_next; list; list= next) + { + next= list->meh_next; + my_free((gptr) list, MYF(0)); + } + my_errmsgs_list= &my_errmsgs_globerrs; +} diff --git a/mysys/my_file.c b/mysys/my_file.c index c97a512f8a1..44bacf55307 100644 --- a/mysys/my_file.c +++ b/mysys/my_file.c @@ -32,7 +32,7 @@ May be more or less than max_file_limit! */ -#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) && !defined(HAVE_mit_thread) +#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) #ifndef RLIM_INFINITY #define RLIM_INFINITY ((uint) 0xffffffff) @@ -71,25 +71,6 @@ static uint set_max_open_files(uint max_file_limit) DBUG_RETURN(max_file_limit); } -#elif defined (OS2) - -static uint set_max_open_files(uint max_file_limit) -{ - LONG cbReqCount; - ULONG cbCurMaxFH0; - APIRET ulrc; - DBUG_ENTER("set_max_open_files"); - - /* get current limit */ - cbReqCount = 0; - DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH0); - - /* set new limit */ - if ((cbReqCount = max_file_limit - cbCurMaxFH0) > 0) - ulrc = DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH); - DBUG_RETURN(cbCurMaxFH0); -} - #else static int set_max_open_files(uint max_file_limit) { @@ -125,7 +106,10 @@ uint my_set_max_open_files(uint files) DBUG_RETURN(MY_NFILE); /* Copy any initialized files */ - memcpy((char*) tmp, (char*) my_file_info, sizeof(*tmp) * my_file_limit); + memcpy((char*) tmp, (char*) my_file_info, + sizeof(*tmp) * min(my_file_limit, files)); + bzero((char*) (tmp + my_file_limit), + max((int) (files- my_file_limit), 0)*sizeof(*tmp)); my_free_open_file_info(); /* Free if already allocated */ my_file_info= tmp; my_file_limit= files; @@ -139,8 +123,12 @@ void my_free_open_file_info() DBUG_ENTER("my_free_file_info"); if (my_file_info != my_file_info_default) { + /* Copy data back for my_print_open_files */ + memcpy((char*) my_file_info_default, my_file_info, + sizeof(*my_file_info_default)* MY_NFILE); my_free((char*) my_file_info, MYF(0)); my_file_info= my_file_info_default; + my_file_limit= MY_NFILE; } DBUG_VOID_RETURN; } diff --git a/mysys/my_gethostbyname.c b/mysys/my_gethostbyname.c index 434a00bab11..067fdfee9db 100644 --- a/mysys/my_gethostbyname.c +++ b/mysys/my_gethostbyname.c @@ -18,7 +18,7 @@ /* Thread safe version of gethostbyname_r() */ #include "mysys_priv.h" -#if !defined(MSDOS) && !defined(__WIN__) +#if !defined(__WIN__) #include <netdb.h> #endif #include <my_net.h> diff --git a/mysys/my_getncpus.c b/mysys/my_getncpus.c new file mode 100644 index 00000000000..82e87dee2e4 --- /dev/null +++ b/mysys/my_getncpus.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2006 MySQL AB + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* get the number of (online) CPUs */ + +#include "mysys_priv.h" +#include <unistd.h> + +static int ncpus=0; + +#ifdef _SC_NPROCESSORS_ONLN +int my_getncpus() +{ + if (!ncpus) + ncpus= sysconf(_SC_NPROCESSORS_ONLN); + return ncpus; +} + +#else +/* unknown */ +int my_getncpus() +{ + return 2; +} + +#endif + diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 250c10e8479..c7bd2dd0a0c 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -490,7 +490,7 @@ invalid value '%s'\n", } get_one_option(optp->id, optp, argument); - (*argc)--; /* option handled (short or long), decrease argument count */ + (*argc)--; /* option handled (short or long), decrease argument count */ } else /* non-option found */ (*argv)[argvpos++]= cur_arg; @@ -940,8 +940,8 @@ void my_print_variables(const struct my_option *options) (*getopt_get_addr)("", 0, optp) : optp->value); if (value) { - printf("%s", optp->name); - length= (uint) strlen(optp->name); + printf("%s ", optp->name); + length= (uint) strlen(optp->name)+1; for (; length < name_space; length++) putchar(' '); switch ((optp->var_type & GET_TYPE_MASK)) { diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c index 3870a5d61b0..c258db8b126 100644 --- a/mysys/my_getwd.c +++ b/mysys/my_getwd.c @@ -21,19 +21,11 @@ #ifdef HAVE_GETWD #include <sys/param.h> #endif -#if defined(MSDOS) || defined(__WIN__) +#if defined(__WIN__) #include <m_ctype.h> #include <dos.h> #include <direct.h> #endif -#if defined(OS2) -#include <direct.h> -#endif - -#ifdef __EMX__ -/* chdir2 support also drive change */ -#define chdir _chdir2 -#endif /* Gets current working directory in buff. Directory is allways ended with FN_LIBCHAR */ @@ -46,11 +38,9 @@ int my_getwd(my_string buf, uint size, myf MyFlags) DBUG_ENTER("my_getwd"); DBUG_PRINT("my",("buf: 0x%lx size: %d MyFlags %d", (long) buf,size,MyFlags)); -#if ! defined(MSDOS) if (curr_dir[0]) /* Current pos is saved here */ VOID(strmake(buf,&curr_dir[0],size-1)); else -#endif { #if defined(HAVE_GETCWD) if (!getcwd(buf,size-2) && MyFlags & MY_WME) @@ -94,48 +84,13 @@ int my_setwd(const char *dir, myf MyFlags) int res; size_s length; my_string start,pos; -#if defined(VMS) || defined(MSDOS) || defined(OS2) +#if defined(VMS) char buff[FN_REFLEN]; #endif DBUG_ENTER("my_setwd"); DBUG_PRINT("my",("dir: '%s' MyFlags %d", dir, MyFlags)); start=(my_string) dir; -#if defined(MSDOS) || defined(OS2) /* OS2/MSDOS chdir can't change drive */ -#if !defined(_DDL) && !defined(WIN32) - if ((pos=(char*) strchr(dir,FN_DEVCHAR)) != 0) - { - uint drive,drives; - - pos++; /* Skip FN_DEVCHAR */ - drive=(uint) (my_toupper(&my_charset_latin1,dir[0])-'A'+1); - drives= (uint) -1; - if ((pos-(byte*) dir) == 2 && drive > 0 && drive < 32) - { -#ifdef OS2 - _chdrive(drive); - drives = _getdrive(); -#else - _dos_setdrive(drive,&drives); - _dos_getdrive(&drives); -#endif - } - if (drive != drives) - { - *pos='\0'; /* Dir is now only drive */ - my_errno=errno; - my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),dir,ENOENT); - DBUG_RETURN(-1); - } - dir=pos; /* drive changed, change now path */ - } -#endif - if (*((pos=strend(dir)-1)) == FN_LIBCHAR && pos != dir) - { - strmov(buff,dir)[-1]=0; /* Remove last '/' */ - dir=buff; - } -#endif /* MSDOS*/ if (! dir[0] || (dir[0] == FN_LIBCHAR && dir[1] == 0)) dir=FN_ROOTDIR; #ifdef VMS diff --git a/mysys/my_init.c b/mysys/my_init.c index cc4bef10e8d..a553d13eaa0 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -86,13 +86,10 @@ my_bool my_init(void) #endif if (my_thread_global_init()) return 1; -#if !defined( __WIN__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined( __WIN__) && !defined(__NETWARE__) sigfillset(&my_signals); /* signals blocked by mf_brkhant */ #endif #endif /* THREAD */ -#ifdef UNIXWARE_7 - (void) isatty(0); /* Go around connect() bug in UW7 */ -#endif { DBUG_ENTER("my_init"); DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown")); @@ -133,7 +130,10 @@ void my_end(int infoflag) */ FILE *info_file= DBUG_FILE; my_bool print_info= (info_file != stderr); - DBUG_ENTER("my_end"); + /* We do not use DBUG_ENTER here, as after cleanup DBUG is no longer + operational, so we cannot use DBUG_RETURN. + */ + DBUG_PRINT("info",("Shutting down")); if (!info_file) { info_file= stderr; @@ -149,9 +149,11 @@ void my_end(int infoflag) sprintf(errbuff[0],EE(EE_OPEN_WARNING),my_file_opened,my_stream_opened); (void) my_message_no_curses(EE_OPEN_WARNING,errbuff[0],ME_BELL); DBUG_PRINT("error",("%s",errbuff[0])); + my_print_open_files(); } } free_charsets(); + my_error_unregister_all(); my_once_free(); if ((infoflag & MY_GIVE_INFO) || print_info) @@ -179,7 +181,7 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals, rus.ru_nvcsw, rus.ru_nivcsw); #endif -#if ( defined(MSDOS) || defined(__NETWARE__) ) && !defined(__WIN__) +#if defined(__NETWARE__) && !defined(__WIN__) fprintf(info_file,"\nRun time: %.1f\n",(double) clock()/CLOCKS_PER_SEC); #endif #if defined(SAFEMALLOC) @@ -206,7 +208,8 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", Check on destroying of mutexes. A few may be left that will get cleaned up by C++ destructors */ - safe_mutex_end(infoflag & MY_GIVE_INFO ? stderr : (FILE *) 0); + safe_mutex_end((infoflag & (MY_GIVE_INFO | MY_CHECK_ERROR)) ? stderr : + (FILE *) 0); #endif /* defined(SAFE_MUTEX) */ #endif /* THREAD */ diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 75e31c4d555..86b1c2d5851 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -14,9 +14,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* TODO: check for overun of memory for names. */ -/* Convert MSDOS-TIME to standar time_t */ +/* Convert MSDOS-TIME to standar time_t (still needed?) */ -#define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" #include <m_string.h> #include <my_dir.h> /* Structs used by my_dir,includes sys/types */ @@ -25,9 +24,7 @@ # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) #else -#ifndef OS2 # define dirent direct -#endif # define NAMLEN(dirent) (dirent)->d_namlen # if defined(HAVE_SYS_NDIR_H) # include <sys/ndir.h> @@ -38,7 +35,7 @@ # if defined(HAVE_NDIR_H) # include <ndir.h> # endif -# if defined(MSDOS) || defined(__WIN__) +# if defined(__WIN__) # include <dos.h> # ifdef __BORLANDC__ # include <dir.h> @@ -51,10 +48,6 @@ #include <descrip.h> #endif -#ifdef OS2 -#include "my_os2dirsrch.h" -#endif - #if defined(THREAD) && defined(HAVE_READDIR_R) #define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C) #else @@ -99,7 +92,7 @@ static int comp_names(struct fileinfo *a, struct fileinfo *b) } /* comp_names */ -#if !defined(MSDOS) && !defined(__WIN__) +#if !defined(__WIN__) MY_DIR *my_dir(const char *path, myf MyFlags) { @@ -352,7 +345,7 @@ my_string directory_file_name (my_string dst, const char *src) #endif /* VMS */ } /* directory_file_name */ -#elif defined(WIN32) +#else /* ***************************************************************************** @@ -391,7 +384,7 @@ MY_DIR *my_dir(const char *path, myf MyFlags) *tmp_file++= '.'; /* From current dev-dir */ if (tmp_file[-1] != FN_LIBCHAR) *tmp_file++ =FN_LIBCHAR; - tmp_file[0]='*'; /* MSDOS needs this !??? */ + tmp_file[0]='*'; /* Windows needs this !??? */ tmp_file[1]='.'; tmp_file[2]='*'; tmp_file[3]='\0'; @@ -514,109 +507,7 @@ error: DBUG_RETURN((MY_DIR *) NULL); } /* my_dir */ -#else /* MSDOS and not WIN32 */ - - -/****************************************************************************** -** At MSDOS you always get stat of files, but time is in packed MSDOS-format -******************************************************************************/ - -MY_DIR *my_dir(const char* path, myf MyFlags) -{ - char *buffer; - MY_DIR *result= 0; - FILEINFO finfo; - DYNAMIC_ARRAY *dir_entries_storage; - MEM_ROOT *names_storage; - struct find_t find; - ushort mode; - char tmp_path[FN_REFLEN],*tmp_file,attrib; - DBUG_ENTER("my_dir"); - DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags)); - - /* Put LIB-CHAR as last path-character if not there */ - - tmp_file=tmp_path; - if (!*path) - *tmp_file++ ='.'; /* From current dir */ - tmp_file= strmov(tmp_file,path); - if (tmp_file[-1] == FN_DEVCHAR) - *tmp_file++= '.'; /* From current dev-dir */ - if (tmp_file[-1] != FN_LIBCHAR) - *tmp_file++ =FN_LIBCHAR; - tmp_file[0]='*'; /* MSDOS needs this !??? */ - tmp_file[1]='.'; - tmp_file[2]='*'; - tmp_file[3]='\0'; - - if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find)) - goto error; - - if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + - ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) + - sizeof(MEM_ROOT), MyFlags))) - goto error; - - dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); - names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) + - ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))); - - if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO), - ENTRIES_START_SIZE, ENTRIES_INCREMENT)) - { - my_free((gptr) buffer,MYF(0)); - goto error; - } - init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE); - - /* MY_DIR structure is allocated and completly initialized at this point */ - result= (MY_DIR*)buffer; - - do - { - if (!(finfo.name= strdup_root(names_storage, find.name))) - goto error; - - if (MyFlags & MY_WANT_STAT) - { - if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage, - sizeof(MY_STAT)))) - goto error; - - bzero(finfo.mystat, sizeof(MY_STAT)); - finfo.mystat->st_size= find.size; - mode= MY_S_IREAD; attrib= find.attrib; - if (!(attrib & _A_RDONLY)) - mode|= MY_S_IWRITE; - if (attrib & _A_SUBDIR) - mode|= MY_S_IFDIR; - finfo.mystat->st_mode= mode; - finfo.mystat->st_mtime= ((uint32) find.wr_date << 16) + find.wr_time; - } - else - finfo.mystat= NULL; - - if (push_dynamic(dir_entries_storage, (gptr)&finfo)) - goto error; - - } while (_dos_findnext(&find) == 0); - - result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; - result->number_off_files= dir_entries_storage->elements; - - if (!(MyFlags & MY_DONT_SORT)) - qsort((void *) result->dir_entry, result->number_off_files, - sizeof(FILEINFO), (qsort_cmp) comp_names); - DBUG_RETURN(result); - -error: - my_dirend(result); - if (MyFlags & MY_FAE+MY_WME) - my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno); - DBUG_RETURN((MY_DIR *) NULL); -} /* my_dir */ - -#endif /* WIN32 && MSDOS */ +#endif /* __WIN__ */ /**************************************************************************** ** File status diff --git a/mysys/my_lock.c b/mysys/my_lock.c index a07f0c072a0..c0522ee849d 100644 --- a/mysys/my_lock.c +++ b/mysys/my_lock.c @@ -25,11 +25,6 @@ #ifdef __WIN__ #include <sys/locking.h> #endif -#ifdef __EMX__ -#define INCL_BASE -#define INCL_NOPMAPI -#include <os2emx.h> -#endif #ifdef __NETWARE__ #include <nks/fsio.h> #endif @@ -102,11 +97,6 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length, DBUG_RETURN(0); } } -#elif defined(__EMX__) || defined(OS2) - - if (!_lock64( fd, locktype, start, length, MyFlags)) - DBUG_RETURN(0); - #elif defined(HAVE_LOCKING) /* Windows */ { diff --git a/mysys/my_lread.c b/mysys/my_lread.c deleted file mode 100644 index 1399b197119..00000000000 --- a/mysys/my_lread.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "mysys_priv.h" -#include "mysys_err.h" - - /* Read a chunk of bytes from a file */ - -uint32 my_lread(int Filedes, byte *Buffer, uint32 Count, myf MyFlags) - /* File descriptor */ - /* Buffer must be at least count bytes */ - /* Max number of bytes returnd */ - /* Flags on what to do on error */ -{ - uint32 readbytes; - DBUG_ENTER("my_lread"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, (long) Buffer, (ulong) Count, MyFlags)); - - DBUG_PRINT("error", ("Deprecated my_lread() function should not be used.")); - - /* Temp hack to get count to int32 while read wants int */ - if ((readbytes = (uint32) read(Filedes, Buffer, (uint) Count)) != Count) - { - my_errno=errno; - if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) - { - if (readbytes == MY_FILE_ERROR) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),errno); - else - if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),errno); - } - if (readbytes == MY_FILE_ERROR || MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN((uint32) -1); /* Return med felkod */ - } - if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Ok vid l{sning */ - DBUG_RETURN(readbytes); -} /* my_lread */ diff --git a/mysys/my_lwrite.c b/mysys/my_lwrite.c deleted file mode 100644 index d26825397e3..00000000000 --- a/mysys/my_lwrite.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include "mysys_priv.h" -#include "mysys_err.h" - - /* Write a chunk of bytes to a file */ - -uint32 my_lwrite(int Filedes, const byte *Buffer, uint32 Count, myf MyFlags) -{ - uint32 writenbytes; - DBUG_ENTER("my_lwrite"); - DBUG_PRINT("my",("Fd: %d Buffer: 0x%lx Count: %lu MyFlags: %d", - Filedes, (long) Buffer, (ulong) Count, MyFlags)); - - DBUG_PRINT("error", ("Deprecated my_lwrite() function should not be used.")); - - /* Temp hack to get count to int32 while write wants int */ - if ((writenbytes = (uint32) write(Filedes, Buffer, (uint) Count)) != Count) - { - my_errno=errno; - if (writenbytes == (uint32) -1 || MyFlags & (MY_NABP | MY_FNABP)) - { - if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) - { - my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),errno); - } - DBUG_RETURN((uint32) -1); /* Return med felkod */ - } - } - if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Ok vid l{sning */ - DBUG_RETURN(writenbytes); -} /* my_lwrite */ diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index 3baf55d4c57..3601a533480 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -82,7 +82,7 @@ char *my_strdup(const char *from, myf my_flags) } -char *my_strdup_with_length(const char *from, uint length, myf my_flags) +char *my_strndup(const char *from, uint length, myf my_flags) { gptr ptr; if ((ptr=my_malloc(length+1,my_flags)) != 0) diff --git a/mysys/my_memmem.c b/mysys/my_memmem.c index 682a1314f09..9230337409d 100644 --- a/mysys/my_memmem.c +++ b/mysys/my_memmem.c @@ -1,4 +1,20 @@ -#include "my_base.h" +/* Copyright (C) 2000 MySQL AB + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <my_global.h> +#include <m_string.h> /* my_memmem, port of a GNU extension. diff --git a/mysys/my_mkdir.c b/mysys/my_mkdir.c index 25176e4b823..676c6c1cd51 100644 --- a/mysys/my_mkdir.c +++ b/mysys/my_mkdir.c @@ -26,7 +26,7 @@ int my_mkdir(const char *dir, int Flags, myf MyFlags) DBUG_ENTER("my_dir"); DBUG_PRINT("enter",("dir: %s",dir)); -#if defined(__WIN__) || defined(OS2) +#if defined(__WIN__) if (mkdir((char*) dir)) #else if (mkdir((char*) dir, Flags & my_umask_dir)) diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index 147bdfdcbf2..023a06fd896 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -35,22 +35,19 @@ static SECURITY_ATTRIBUTES mmap_security_attributes= void *my_mmap(void *addr, size_t len, int prot, int flags, int fd, my_off_t offset) { - DWORD flProtect=0; HANDLE hFileMap; LPVOID ptr; HANDLE hFile= (HANDLE)_get_osfhandle(fd); if (hFile == INVALID_HANDLE_VALUE) return MAP_FAILED; - flProtect|=SEC_COMMIT; - hFileMap=CreateFileMapping(hFile, &mmap_security_attributes, PAGE_READWRITE, 0, (DWORD) len, NULL); if (hFileMap == 0) return MAP_FAILED; ptr=MapViewOfFile(hFileMap, - flags & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ, + prot & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ, (DWORD)(offset >> 32), (DWORD)offset, len); /* diff --git a/mysys/my_net.c b/mysys/my_net.c index 136d987f500..81d977210f8 100644 --- a/mysys/my_net.c +++ b/mysys/my_net.c @@ -19,7 +19,7 @@ #include <m_string.h> /* for thread safe my_inet_ntoa */ -#if !defined(MSDOS) && !defined(__WIN__) +#if !defined(__WIN__) #include <netdb.h> #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> @@ -30,7 +30,7 @@ #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif -#endif /* !defined(MSDOS) && !defined(__WIN__) */ +#endif /* !defined(__WIN__) */ void my_inet_ntoa(struct in_addr in, char *buf) { diff --git a/mysys/my_once.c b/mysys/my_once.c index d83eba95b9d..fcb5af3ccbd 100644 --- a/mysys/my_once.c +++ b/mysys/my_once.c @@ -74,6 +74,8 @@ gptr my_once_alloc(unsigned int Size, myf MyFlags) point= (gptr) ((char*) next+ (next->size-next->left)); next->left-= Size; + if (MyFlags & MY_ZEROFILL) + bzero(point, Size); return(point); } /* my_once_alloc */ diff --git a/mysys/my_open.c b/mysys/my_open.c index 2ba84f92ac2..21bdedddc48 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -13,12 +13,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "mysys_priv.h" #include "mysys_err.h" #include <my_dir.h> #include <errno.h> -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#if defined(__WIN__) #include <share.h> #endif @@ -44,7 +43,7 @@ File my_open(const char *FileName, int Flags, myf MyFlags) DBUG_ENTER("my_open"); DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d", FileName, Flags, MyFlags)); -#if defined(MSDOS) || defined(__WIN__) || defined(__EMX__) || defined(OS2) +#if defined(__WIN__) /* Check that we don't try to open or create a file name that may cause problems for us in the future (like PRN) @@ -167,9 +166,17 @@ File my_register_filename(File fd, const char *FileName, enum file_type else my_errno=errno; DBUG_PRINT("error",("Got error %d on open",my_errno)); - if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) - my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG), + if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) { + if (my_errno == EMFILE) { + DBUG_PRINT("error",("print err: %d",EE_OUT_OF_FILERESOURCES)); + my_error(EE_OUT_OF_FILERESOURCES, MYF(ME_BELL+ME_WAITTANG), FileName, my_errno); + } else { + DBUG_PRINT("error",("print err: %d",error_message_number)); + my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG), + FileName, my_errno); + } + } return(fd); } @@ -350,3 +357,24 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode) return fh; /* return handle */ } #endif /* __WIN__ */ + + +#ifdef EXTRA_DEBUG + +void my_print_open_files(void) +{ + if (my_file_opened | my_stream_opened) + { + uint i; + for (i= 0 ; i < my_file_limit ; i++) + { + if (my_file_info[i].type != UNOPEN) + { + fprintf(stderr, EE(EE_FILE_NOT_CLOSED), my_file_info[i].name, i); + fputc('\n', stderr); + } + } + } +} + +#endif diff --git a/mysys/my_os2cond.c b/mysys/my_os2cond.c deleted file mode 100644 index f0cf91404d2..00000000000 --- a/mysys/my_os2cond.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (C) Yuri Dario & 2000 MySQL AB - All the above parties has a full, independent copyright to - the following code, including the right to use the code in - any manner without any demands from the other parties. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/***************************************************************************** -** The following is a simple implementation of posix conditions -*****************************************************************************/ - -#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */ -#include "mysys_priv.h" -#if defined(THREAD) && defined(OS2) -#include <m_string.h> -#include <process.h> -#include <sys/timeb.h> - -int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) -{ - cond->waiting= 0; - /* Warp3 FP29 or Warp4 FP4 or better required */ - if (DosCreateEventSem(NULL, &cond->semaphore, 0x0800, 0)) - return ENOMEM; - return 0; -} - -int pthread_cond_destroy(pthread_cond_t *cond) -{ - for (;;) - { - APIRET rc; - if ((rc= DosCloseEventSem(cond->semaphore)) != 301) - return rc ? EINVAL : 0; - DosPostEventSem(cond->semaphore); - } -} - - -int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) -{ - int rval= 0; - cond->waiting++; - if (mutex) - pthread_mutex_unlock(mutex); - if (DosWaitEventSem(cond->semaphore, SEM_INDEFINITE_WAIT)) - rval= EINVAL; - if (mutex) - pthread_mutex_lock(mutex); - cond->waiting--; - return rval; -} - -int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - struct timespec *abstime) -{ - struct timeb curtime; - int result; - long timeout; - int rval= 0; - - _ftime(&curtime); - timeout= ((long) (abstime->ts_sec - curtime.time) * 1000L + - (long) ((abstime->ts_nsec / 1000) - curtime.millitm) / 1000L); - if (timeout < 0) /* Some safety */ - timeout= 0L; - - cond->waiting++; - - if (mutex) - pthread_mutex_unlock(mutex); - if (DosWaitEventSem(cond->semaphore, timeout) != 0) - rval= ETIMEDOUT; - if (mutex) - pthread_mutex_lock(mutex); - - cond->waiting--; - - return rval; -} - - -int pthread_cond_signal(pthread_cond_t *cond) -{ - /* Bring the next thread off the condition queue: */ - DosPostEventSem(cond->semaphore); - return 0; -} - - -int pthread_cond_broadcast(pthread_cond_t *cond) -{ - int i; - /* Enter a loop to bring all threads off the condition queue */ - for (i= cond->waiting; i--;) - DosPostEventSem(cond->semaphore); - return 0; -} - - -int pthread_attr_init(pthread_attr_t *connect_att) -{ - connect_att->dwStackSize= 0; - connect_att->dwCreatingFlag= 0; - connect_att->priority= 0; - return 0; -} - -int pthread_attr_setstacksize(pthread_attr_t *connect_att, DWORD stack) -{ - connect_att->dwStackSize= stack; - return 0; -} - -int pthread_attr_setprio(pthread_attr_t *connect_att, int priority) -{ - connect_att->priority= priority; - return 0; -} - -int pthread_attr_destroy(pthread_attr_t *connect_att) -{ - bzero((gptr) connect_att, sizeof(*connect_att)); - return 0; -} - -/**************************************************************************** -** Fix localtime_r() to be a bit safer -****************************************************************************/ - -struct tm *localtime_r(const time_t *timep, struct tm *tmp) -{ - if (*timep == (time_t) - 1) /* This will crash win32 */ - { - bzero(tmp, sizeof(*tmp)); - } - else - { - struct tm *res= localtime(timep); - if (!res) /* Wrong date */ - { - bzero(tmp, sizeof(*tmp)); /* Keep things safe */ - return 0; - } - *tmp= *res; - } - return tmp; -} -#endif /* __WIN__ */ diff --git a/mysys/my_os2dirsrch.c b/mysys/my_os2dirsrch.c deleted file mode 100644 index 27e774c8e04..00000000000 --- a/mysys/my_os2dirsrch.c +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright (C) Yuri Dario & 2000-2003 MySQL AB - All the above parties has a full, independent copyright to - the following code, including the right to use the code in - any manner without any demands from the other parties. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - - -/* Win32 directory search emulation */ - -#if defined(OS2) - -long _findfirst( char* path, struct _finddata_t* dos_file) -{ - HDIR hdir = HDIR_CREATE; - APIRET rc; - FILEFINDBUF3 buf3; - ULONG entries = 1; - -#ifdef _DEBUG - printf( "_findfirst path %s\n", path); -#endif - - memset( &buf3, 0, sizeof( buf3)); - rc = DosFindFirst( - path, /* The ASCIIZ path name of the file or subdirectory to be found. */ - &hdir, /* The handle associated with this DosFindFirst request. */ - FILE_NORMAL | FILE_DIRECTORY, /* Attribute value that determines the file objects to be searched for. */ - &buf3, /* Result buffer. */ - sizeof( buf3), /* The length, in bytes, of pfindbuf. */ - &entries, /* Pointer to the number of entries: */ - FIL_STANDARD); /* The level of file information required. */ - -#ifdef _DEBUG - printf( "_findfirst rc=%d hdir=%d entries=%d->%s\n", rc, hdir, entries, - buf3.achName); -#endif - - if (rc /* && entries == 0 */) - return -1; - - if (dos_file) - { - memset( dos_file, 0, sizeof( struct _finddata_t)); - strcpy( dos_file->name, buf3.achName); - dos_file->size = buf3.cbFile; - dos_file->attrib = buf3.attrFile; - } - return (ULONG) hdir; -} - - -long _findnext( long hdir, struct _finddata_t* dos_file) -{ - APIRET rc; - FILEFINDBUF3 buf3; - ULONG entries = 1; - - memset( &buf3, 0, sizeof( buf3)); - rc = DosFindNext(hdir, - &buf3, /* Result buffer. */ - sizeof( buf3), /* Length, in bytes, of pfindbuf. */ - &entries); /* Pointer to the number of entries */ - -#ifdef _DEBUG - printf( "_findnext rc=%d hdir=%d entries=%d->%s\n", rc, hdir, entries, - buf3.achName); -#endif - - if (rc /* && entries == 0 */) - return -1; - - if (dos_file) - { - memset( dos_file, 0, sizeof( struct _finddata_t)); - strcpy( dos_file->name, buf3.achName); - dos_file->size = buf3.cbFile; - dos_file->attrib = buf3.attrFile; - } - return 0; -} - -void _findclose( long hdir) -{ - APIRET rc; - - rc = DosFindClose( hdir); -#ifdef _DEBUG - printf( "_findclose rc=%d hdir=%d\n", rc, hdir); -#endif -} - -DIR* opendir(char* path) -{ - DIR* dir = (DIR*) calloc(1, sizeof( DIR)); - char buffer[260]; - APIRET rc; - ULONG entries = 1; - - strmov(strmov(buffer, path), "*.*"); - -#ifdef _DEBUG - printf( "_findfirst path %s\n", buffer); -#endif - - dir->hdir = HDIR_CREATE; - memset( &dir->buf3, 0, sizeof( dir->buf3)); - rc = DosFindFirst( - buffer, /* Address of the ASCIIZ path name of the file or subdirectory to be found. */ - &dir->hdir, /* Address of the handle associated with this DosFindFirst request. */ - FILE_NORMAL | FILE_DIRECTORY, /* Attribute value that determines the file objects to be searched for. */ - &dir->buf3, /* Result buffer. */ - sizeof( dir->buf3), /* The length, in bytes, of pfindbuf. */ - &entries, /* Pointer to the number of entries: */ - FIL_STANDARD); /* The level of file information required. */ - -#ifdef _DEBUG - printf( "opendir rc=%d hdir=%d entries=%d->%s\n", rc, dir->hdir, entries, dir->buf3.achName); -#endif - - if (rc /* && entries == 0 */) - return NULL; - - return dir; -} - - -struct dirent* readdir( DIR* dir) -{ - APIRET rc; - ULONG entries = 1; - - if (!dir->buf3.achName[0]) /* file not found on previous query */ - return NULL; - - /* copy last file name */ - strcpy( dir->ent.d_name, dir->buf3.achName); - - /* query next file */ - memset( &dir->buf3, 0, sizeof( dir->buf3)); - rc= DosFindNext( - dir->hdir, - &dir->buf3, /* Result buffer. */ - sizeof(dir->buf3), /* Length, in bytes, of pfindbuf. */ - &entries); /* Pointer to the number of entries */ - -#ifdef _DEBUG - printf( "_findnext rc=%d hdir=%d entries=%d->%s\n", rc, dir->hdir, entries, - dir->buf3.achName); -#endif - - if (rc /* && entries == 0 */) - *dir->buf3.achName= 0; /* reset name for next query */ - - return &dir->ent; -} - - -int closedir (DIR *dir) -{ - APIRET rc; - - rc = DosFindClose( dir->hdir); -#ifdef _DEBUG - printf( "_findclose rc=%d hdir=%d\n", rc, dir->hdir); -#endif - free(dir); - return 0; -} - -#endif /* OS2 */ diff --git a/mysys/my_os2dirsrch.h b/mysys/my_os2dirsrch.h deleted file mode 100644 index e3af6740769..00000000000 --- a/mysys/my_os2dirsrch.h +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (C) Yuri Dario & 2000 MySQL AB - All the above parties has a full, independent copyright to - the following code, including the right to use the code in - any manner without any demands from the other parties. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* Win32 directory search emulation */ - -#ifndef __MY_OS2DIRSRCH2_H__ -#define __MY_OS2DIRSRCH2_H__ - -#ifdef __cplusplus_00 -extern "C" { -#endif - -struct _finddata_t -{ - unsigned attrib; -#ifdef NOT_USED - unsigned long time_create; /* -1 for FAT file systems */ - unsigned long time_access; /* -1 for FAT file systems */ - unsigned long time_write; -#endif - unsigned long size; - char name[260]; -#ifdef NOT_USED - uint16 wr_date; - uint16 wr_time; -#endif -}; - - -struct dirent -{ -#ifdef NOT_USED - unsigned attrib; - unsigned long time_create; /* -1 for FAT file systems */ - unsigned long time_access; /* -1 for FAT file systems */ - unsigned long time_write; - unsigned long size; -#endif - char d_name[260]; -#ifdef NOT_USED - uint16 wr_date; - uint16 wr_time; -#endif -}; - -struct DIR -{ - HDIR hdir; - FILEFINDBUF3 buf3; - struct dirent ent; -}; - -DIR *opendir ( char *); -struct dirent *readdir (DIR *); -int closedir (DIR *); - -#ifdef NOT_USED -#define _A_NORMAL FILE_NORMAL -#define _A_SUBDIR FILE_DIRECTORY -#define _A_RDONLY FILE_READONLY - -long _findfirst( char*, struct _finddata_t*); -long _findnext( long, struct _finddata_t*); -void _findclose( long); -#endif - -#ifdef __cplusplus_00 -} -#endif - -#endif /* __MY_OS2DIRSRCH2_H__ */ diff --git a/mysys/my_os2dlfcn.c b/mysys/my_os2dlfcn.c deleted file mode 100644 index 74be940d0d4..00000000000 --- a/mysys/my_os2dlfcn.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) Yuri Dario & 2000 MySQL AB - All the above parties has a full, independent copyright to - the following code, including the right to use the code in - any manner without any demands from the other parties. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* - * dlfcn::Unix dynamic loading for OS/2 - * - * Compatibility layer for dynamic loading. - * Only minimal implementation - * -*/ - -#define RTLD_LAZY 0 -#define RTLD_NOW 0 - -void* dlopen( char* path, int flag); -char* dlerror( void); -void* dlsym( void* hmod, char* fn); -void dlclose( void* hmod); - -char fail[ 256]; - -void* dlopen( char* path, int flag) -{ - APIRET rc; - HMODULE hmod; - - rc = DosLoadModule( fail, sizeof( fail), path, &hmod); - if (rc) - return NULL; - - return (void*) hmod; -} - -char* dlerror( void) -{ - return fail; -} - -void* dlsym( void* hmod, char* fn) -{ - APIRET rc; - PFN addr; - - rc = DosQueryProcAddr( (HMODULE) hmod, 0l, fn, &addr); - if (rc) - return NULL; - - return (void*) addr; -} - -void dlclose( void* hmod) -{ - APIRET rc; - - rc = DosFreeModule( (HMODULE) hmod); - -} diff --git a/mysys/my_os2dlfcn.h0 b/mysys/my_os2dlfcn.h0 deleted file mode 100644 index ec05eebc47b..00000000000 --- a/mysys/my_os2dlfcn.h0 +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) Yuri Dario & 2000 MySQL AB - All the above parties has a full, independent copyright to - the following code, including the right to use the code in - any manner without any demands from the other parties. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ -/* - * dlfcn::Unix dynamic loading for OS/2 - * - * Compatibility layer for dynamic loading. - * Only minimal implementation - * -*/ - -#ifndef __DLFCN_H__ -#define __DLFCN_H__ - -#define RTLD_LAZY 0 -#define RTLD_NOW 0 - -void* dlopen( char* path, int flag); -char* dlerror( void); -void* dlsym( void* hmod, char* fn); -void dlclose( void* hmod); - -#endif diff --git a/mysys/my_os2file64.c b/mysys/my_os2file64.c deleted file mode 100644 index 52156903b80..00000000000 --- a/mysys/my_os2file64.c +++ /dev/null @@ -1,394 +0,0 @@ -/* Copyright (C) Yuri Dario & 2000 MySQL AB - All the above parties has a full, independent copyright to - the following code, including the right to use the code in - any manner without any demands from the other parties. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -void _OS2errno( APIRET rc); -longlong _lseek64( int fd, longlong offset, int seektype); -int _lock64( int fd, int locktype, my_off_t start, - my_off_t length, myf MyFlags); -int _sopen64( const char *name, int oflag, int shflag, int mask); - -/* - This class is used to define a global c++ variable, that - is initialized before main() gets called. -*/ - -class File64bit -{ - public: - File64bit(); /* default constructor */ -} initFile64bit; - -static APIRET (* APIENTRY _DosOpenL)(PCSZ pszFileName, - PHFILE phf, - PULONG pulAction, - LONGLONG cbFile, - ULONG ulAttribute, - ULONG fsOpenFlags, - ULONG fsOpenMode, - PEAOP2 peaop2); -static APIRET (* APIENTRY _DosSetFilePtrL)(HFILE hFile, - LONGLONG ib, - ULONG method, - PLONGLONG ibActual); -static APIRET (* APIENTRY _DosSetFileLocksL)(HFILE hFile, - PFILELOCKL pflUnlock, - PFILELOCKL pflLock, - ULONG timeout, - ULONG flags); - -#define EIO EINVAL -#define ESPIPE EBADSEEK - - -static unsigned char const errno_tab[] = -{ - 0 , EINVAL, ENOENT, ENOENT, EMFILE, /* 0..4 */ - EACCES, EBADF, EIO, ENOMEM, EIO, /* 5..9 */ - EINVAL, ENOEXEC,EINVAL, EINVAL, EINVAL, /* 10..14 */ - ENOENT, EBUSY, EXDEV, ENOENT, EROFS, /* 15..19 */ - EIO, EIO, EIO, EIO, EIO, /* 20..24 */ - EIO, EIO, EIO, ENOSPC, EIO, /* 25..29 */ - EIO, EIO, EACCES, EACCES, EIO, /* 30..34 */ - EIO, EIO, EIO, EIO, ENOSPC, /* 35..39 */ - EIO, EIO, EIO, EIO, EIO, /* 40..44 */ - EIO, EIO, EIO, EIO, EIO, /* 45..49 */ - EIO, EIO, EIO, EIO, EBUSY, /* 50..54 */ - EIO, EIO, EIO, EIO, EIO, /* 55..59 */ - EIO, ENOSPC, ENOSPC, EIO, EIO, /* 60..64 */ - EACCES, EIO, EIO, EIO, EIO, /* 65..69 */ - EIO, EIO, EIO, EROFS, EIO, /* 70..74 */ - EIO, EIO, EIO, EIO, EIO, /* 75..79 */ - EEXIST, EIO, ENOENT, EIO, EIO, /* 80..84 */ - EIO, EIO, EINVAL, EIO, EAGAIN, /* 85..89 */ - EIO, EIO, EIO, EIO, EIO, /* 90..94 */ - EINTR, EIO, EIO, EIO, EACCES, /* 95..99 */ - ENOMEM, EINVAL, EINVAL, ENOMEM, EINVAL, /* 100..104 */ - EINVAL, ENOMEM, EIO, EACCES, EPIPE, /* 105..109 */ - ENOENT, E2BIG, ENOSPC, ENOMEM, EBADF, /* 110..114 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 115..119 */ - EINVAL, EINVAL, EINVAL, ENOENT, EINVAL, /* 120..124 */ - ENOENT, ENOENT, ENOENT, ECHILD, ECHILD, /* 125..129 */ - EACCES, EINVAL, ESPIPE, EINVAL, EINVAL, /* 130..134 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 135..139 */ - EINVAL, EINVAL, EBUSY, EINVAL, EINVAL, /* 140..144 */ - EINVAL, EINVAL, EINVAL, EBUSY, EINVAL, /* 145..149 */ - EINVAL, EINVAL, ENOMEM, EINVAL, EINVAL, /* 150..154 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 155..159 */ - EINVAL, EINVAL, EINVAL, EINVAL, EAGAIN, /* 160..164 */ - EINVAL, EINVAL, EACCES, EINVAL, EINVAL, /* 165..169 */ - EBUSY, EINVAL, EINVAL, EINVAL, EINVAL, /* 170..174 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 175..179 */ - EINVAL, EINVAL, EINVAL, EINVAL, ECHILD, /* 180..184 */ - EINVAL, EINVAL, ENOENT, EINVAL, EINVAL, /* 185..189 */ - ENOEXEC,ENOEXEC,ENOEXEC,ENOEXEC,ENOEXEC, /* 190..194 */ - ENOEXEC,ENOEXEC,ENOEXEC,ENOEXEC,ENOEXEC, /* 195..199 */ - ENOEXEC,ENOEXEC,ENOEXEC,ENOENT, EINVAL, /* 200..204 */ - EINVAL, ENAMETOOLONG, EINVAL, EINVAL, EINVAL, /* 205..209 */ - EINVAL, EINVAL, EACCES, ENOEXEC,ENOEXEC, /* 210..214 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 215..219 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 220..224 */ - EINVAL, EINVAL, EINVAL, ECHILD, EINVAL, /* 225..229 */ - EINVAL, EBUSY, EAGAIN, ENOTCONN, EINVAL, /* 230..234 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 235..239 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 240..244 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 245..249 */ - EACCES, EACCES, EINVAL, ENOENT, EINVAL, /* 250..254 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 255..259 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 260..264 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 265..269 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 270..274 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 275..279 */ - EINVAL, EINVAL, EINVAL, EINVAL, EEXIST, /* 280..284 */ - EEXIST, EINVAL, EINVAL, EINVAL, EINVAL, /* 285..289 */ - ENOMEM, EMFILE, EINVAL, EINVAL, EINVAL, /* 290..294 */ - EINVAL, EINVAL, EINVAL, EINVAL, EINVAL, /* 295..299 */ - EINVAL, EBUSY, EINVAL, ESRCH, EINVAL, /* 300..304 */ - ESRCH, EINVAL, EINVAL, EINVAL, ESRCH, /* 305..309 */ - EINVAL, ENOMEM, EINVAL, EINVAL, EINVAL, /* 310..314 */ - EINVAL, E2BIG, ENOENT, EIO, EIO, /* 315..319 */ - EINVAL, EINVAL, EINVAL, EINVAL, EAGAIN, /* 320..324 */ - EINVAL, EINVAL, EINVAL, EIO, ENOENT, /* 325..329 */ - EACCES, EACCES, EACCES, ENOENT, ENOMEM /* 330..334 */ -}; - -/* - * Initialize 64bit file access: dynamic load of WSeB API -*/ - File64bit :: File64bit() -{ - HMODULE hDoscalls; - - if (DosQueryModuleHandle("DOSCALLS", &hDoscalls) != NO_ERROR) - return; - - if (DosQueryProcAddr(hDoscalls, 981, NULL, (PFN *)&_DosOpenL) != NO_ERROR) - return; - - if (DosQueryProcAddr(hDoscalls, 988, NULL, (PFN *)&_DosSetFilePtrL) != NO_ERROR) { - _DosOpenL = NULL; - return; - } - - if (DosQueryProcAddr(hDoscalls, 986, NULL, (PFN *)&_DosSetFileLocksL) != NO_ERROR) { - _DosOpenL = NULL; - _DosSetFilePtrL = NULL; - return; - } - /* notify success */ -#ifdef MYSQL_SERVER - printf( "WSeB 64bit file API loaded.\n"); -#endif -} - -void _OS2errno( APIRET rc) -{ - if (rc >= sizeof (errno_tab)) - errno = EINVAL; - else - errno = errno_tab[rc]; -} - - -longlong _lseek64( int fd, longlong offset, int seektype) -{ - APIRET rc; - longlong actual; - - if (_DosSetFilePtrL) - rc = _DosSetFilePtrL( fd, offset, seektype, &actual); - else - { - ULONG ulActual; - rc = DosSetFilePtr( fd, (long) offset, seektype, &ulActual); - actual = ulActual; - } - - if (!rc) - return( actual); /* NO_ERROR */ - - _OS2errno( rc); /* set errno */ - return(-1); /* seek failed */ -} - - -inline APIRET _SetFileLocksL(HFILE hFile, - PFILELOCKL pflUnlock, - PFILELOCKL pflLock, - ULONG timeout, - ULONG flags) -{ - if (_DosSetFileLocksL) - { - APIRET rc; - rc = _DosSetFileLocksL( hFile, pflUnlock, pflLock, timeout, flags); - - /* - on FAT/HPFS/LAN a INVALID_PARAMETER is returned, seems that - only JFS can handle >2GB ranges. - */ - if (rc != 87) - return rc; - /* got INVALID_PARAMETER, fallback to standard call */ - } - - FILELOCK flUnlock = { pflUnlock->lOffset, pflUnlock->lRange }; - FILELOCK flLock = { pflLock->lOffset, pflLock->lRange }; - return DosSetFileLocks( hFile, &flUnlock, &flLock, timeout, flags); -} - - -int _lock64( int fd, int locktype, my_off_t start, - my_off_t length, myf MyFlags) -{ - FILELOCKL LockArea = {0,0}, UnlockArea = {0,0}; - ULONG readonly = 0; - APIRET rc = -1; - - switch (locktype) { - case F_UNLCK: - UnlockArea.lOffset = start; - UnlockArea.lRange = length ? length : LONGLONG_MAX; - break; - - case F_RDLCK: - case F_WRLCK: - LockArea.lOffset = start; - LockArea.lRange = length ? length : LONGLONG_MAX; - readonly = (locktype == F_RDLCK ? 1 : 0); - break; - - default: - errno = EINVAL; - rc = -1; - break; - } - - if (MyFlags & MY_DONT_WAIT) - { - rc = _SetFileLocksL( fd, &UnlockArea, &LockArea, 0, readonly); - /* printf("fd %d, locktype %d, rc %d (dont_wait)\n", fd, locktype, rc); */ - if (rc == 33) { /* Lock Violation */ - - DBUG_PRINT("info",("Was locked, trying with timeout")); - rc = _SetFileLocksL( fd, &UnlockArea, &LockArea, 1 * 1000, readonly); - /* printf( "fd %d, locktype %d, rc %d (dont_wait with timeout)\n", fd, locktype, rc); */ - } - } - else - { - while (rc = _SetFileLocksL( fd, &UnlockArea, &LockArea, 0, readonly) && - (rc == 33)) - { - printf("."); - DosSleep(1 * 1000); - } - /* printf( "fd %d, locktype %d, rc %d (wait2)\n", fd, locktype, rc); */ - } - if (!rc) - return(0); /* NO_ERROR */ - _OS2errno( rc); /* set errno */ - return(-1); /* lock failed */ -} - - -int sopen(const char *name, int oflag, int shflag, int mask) -{ - int fail_errno; - APIRET rc = 0; - HFILE hf = 0; - ULONG ulAction = 0; - LONGLONG cbFile = 0; - ULONG ulAttribute = FILE_NORMAL; - ULONG fsOpenFlags = 0; - ULONG fsOpenMode = 0; - - /* Extract the access mode and sharing mode bits. */ - fsOpenMode = (shflag & 0xFF) | (oflag & 0x03); - - /* - Translate ERROR_OPEN_FAILED to ENOENT unless O_EXCL is set (see - below). - */ - fail_errno = ENOENT; - - /* - Compute `open_flag' depending on `flags'. Note that _SO_CREAT is - set for O_CREAT. - */ - - if (oflag & O_CREAT) - { - if (oflag & O_EXCL) - { - fsOpenFlags = OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; - fail_errno = EEXIST; - } - else if (oflag & O_TRUNC) - fsOpenFlags = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; - else - fsOpenFlags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW; - - if (mask & S_IWRITE) - ulAttribute = FILE_NORMAL; - else - ulAttribute = FILE_READONLY; - - } - else if (oflag & O_TRUNC) - fsOpenFlags = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; - else - fsOpenFlags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW; - - /* Try to open the file and handle errors. */ - if (_DosOpenL) - rc = _DosOpenL( name, &hf, &ulAction, cbFile, - ulAttribute, fsOpenFlags, fsOpenMode, NULL); - else - rc = DosOpen( name, &hf, &ulAction, (LONG) cbFile, - ulAttribute, fsOpenFlags, fsOpenMode, NULL); - - if (rc == ERROR_OPEN_FAILED) - { - errno = fail_errno; - return -1; - } - if (rc != 0) - { - _OS2errno( rc); /* set errno */ - return -1; - } - if (oflag & O_APPEND) - _lseek64( hf, 0L, SEEK_END); - return hf; -} - - -int read(int fd, void *buffer, unsigned int count) -{ - APIRET rc; - ULONG actual; - - rc= DosRead( fd, (PVOID) buffer, count, &actual); - - if (!rc) - return( actual); /* NO_ERROR */ - _OS2errno( rc); /* set errno */ - return(-1); /* read failed */ -} - - -int write(int fd, const void *buffer, unsigned int count) -{ - APIRET rc; - ULONG actual; - - rc = DosWrite( fd, (PVOID) buffer, count, &actual); - - if (!rc) - return( actual); /* NO_ERROR */ - _OS2errno( rc); /* set errno */ - return(-1); /* write failed */ -} - - -int close( int fd) -{ - APIRET rc; - ULONG actual; - - rc = DosClose( fd); - - if (!rc) - return( 0); /* NO_ERROR */ - _OS2errno( rc); /* set errno */ - return(-1); /* close failed */ -} - - -int open( const char *name, int oflag) -{ - return sopen( name, oflag, OPEN_SHARE_DENYNONE, S_IREAD | S_IWRITE); -} - - -int open( const char *name, int oflag, int mask) -{ - return sopen( name, oflag, OPEN_SHARE_DENYNONE, mask); -} diff --git a/mysys/my_os2mutex.c b/mysys/my_os2mutex.c deleted file mode 100644 index 5010d6e8dd5..00000000000 --- a/mysys/my_os2mutex.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>. - * All rights reserved. - * - * Modified and extended by Antony T Curtis <antony.curtis@olcs.net> - * for use with OS/2. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by John Birrell. - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ -#include <stdlib.h> -#include <errno.h> -#ifdef _THREAD_SAFE - -int -pthread_mutex_init(pthread_mutex_t * mutex, - const pthread_mutexattr_t * mutex_attr) -{ - (void) DosCreateMutexSem(NULL,mutex,0,0); - return (0); /* Return the completion status: */ -} - - -int -pthread_mutex_destroy(pthread_mutex_t * mutex) -{ - APIRET rc; - - do - { - rc = DosCloseMutexSem(*mutex); - if (rc == 301) DosReleaseMutexSem(*mutex); - } while (rc == 301); - - *mutex = 0; - return (0); /* Return the completion status: */ -} - - -int -pthread_mutex_lock(pthread_mutex_t * mutex) -{ - APIRET rc; - - rc = DosRequestMutexSem(*mutex,SEM_INDEFINITE_WAIT); - if (rc) - return(EINVAL); - return (0); /* Return the completion status: */ -} - - -int -pthread_mutex_unlock(pthread_mutex_t * mutex) -{ - (void) DosReleaseMutexSem(*mutex); - return (0); /* Return the completion status: */ -} -#endif diff --git a/mysys/my_os2thread.c b/mysys/my_os2thread.c deleted file mode 100644 index e34fd18d596..00000000000 --- a/mysys/my_os2thread.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) Yuri Dario & 2000 MySQL AB - All the above parties has a full, independent copyright to - the following code, including the right to use the code in - any manner without any demands from the other parties. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/***************************************************************************** -** Simulation of posix threads calls for OS/2 -*****************************************************************************/ - -#include "mysys_priv.h" -#if defined(THREAD) && defined(OS2) -#include <m_string.h> -#include <process.h> - -static pthread_mutex_t THR_LOCK_thread; - -struct pthread_map -{ - HANDLE pthreadself; - pthread_handler func; - void * param; -}; - -void win_pthread_init(void) -{ - pthread_mutex_init(&THR_LOCK_thread,NULL); -} - -/* -** We have tried to use '_beginthreadex' instead of '_beginthread' here -** but in this case the program leaks about 512 characters for each -** created thread ! -** As we want to save the created thread handler for other threads to -** use and to be returned by pthread_self() (instead of the Win32 pseudo -** handler), we have to go trough pthread_start() to catch the returned handler -** in the new thread. -*/ - -pthread_handler_t pthread_start(void *param) -{ - DBUG_ENTER("pthread_start"); - pthread_handler func=((struct pthread_map *) param)->func; - void *func_param=((struct pthread_map *) param)->param; - my_thread_init(); /* Will always succeed in windows */ - pthread_mutex_lock(&THR_LOCK_thread); /* Wait for beginthread to return */ - win_pthread_self=((struct pthread_map *) param)->pthreadself; - pthread_mutex_unlock(&THR_LOCK_thread); - free((char*) param); /* Free param from create */ - /* pthread_exit((void*) (*func)(func_param)); */ - (*func)(func_param); - DBUG_RETURN(0); -} - - -int pthread_create(pthread_t *thread_id, pthread_attr_t *attr, - pthread_handler func, void *param) -{ - HANDLE hThread; - struct pthread_map *map; - DBUG_ENTER("pthread_create"); - - if (!(map=(struct pthread_map *)malloc(sizeof(*map)))) - DBUG_RETURN(-1); - map->func=func; - map->param=param; - pthread_mutex_lock(&THR_LOCK_thread); -#ifdef __BORLANDC__ - hThread=(HANDLE)_beginthread((void(_USERENTRY *)(void *)) pthread_start, - attr->dwStackSize ? attr->dwStackSize : - 65535, (void*) map); -#elif defined( OS2) - hThread=(HANDLE)_beginthread((void( _Optlink *)(void *)) pthread_start, NULL, - attr->dwStackSize ? attr->dwStackSize : - 65535, (void*) map); -#else - hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start, - attr->dwStackSize ? attr->dwStackSize : - 65535, (void*) map); -#endif - DBUG_PRINT("info", ("hThread=%lu",(long) hThread)); - *thread_id=map->pthreadself=hThread; - pthread_mutex_unlock(&THR_LOCK_thread); - - if (hThread == (HANDLE) -1) - { - int error=errno; - DBUG_PRINT("error", - ("Can't create thread to handle request (error %d)",error)); - DBUG_RETURN(error ? error : -1); - } -#ifdef OS2 - my_pthread_setprio(hThread, attr->priority); -#else - VOID(SetThreadPriority(hThread, attr->priority)) ; -#endif - DBUG_RETURN(0); -} - - -void pthread_exit(void *a) -{ - _endthread(); -} - -/* This is neaded to get the macro pthread_setspecific to work */ - -int win_pthread_setspecific(void *a,void *b,uint length) -{ - memcpy(a,b,length); - return 0; -} - -#endif diff --git a/mysys/my_os2tls.c b/mysys/my_os2tls.c deleted file mode 100644 index 49100c65516..00000000000 --- a/mysys/my_os2tls.c +++ /dev/null @@ -1,151 +0,0 @@ -/* Copyright (C) Yuri Dario & 2000 MySQL AB - All the above parties has a full, independent copyright to - the following code, including the right to use the code in - any manner without any demands from the other parties. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -DWORD TlsAlloc( void); -BOOL TlsFree( DWORD); -PVOID TlsGetValue( DWORD); -BOOL TlsSetValue( DWORD, PVOID); - -#define TLS_MINIMUM_AVAILABLE 64 - - -PULONG tls_storage; /* TLS local storage */ -DWORD tls_bits[2]; /* TLS in-use bits */ -pthread_mutex_t tls_mutex; /* TLS mutex for in-use bits */ - - -DWORD TlsAlloc( void) -{ - DWORD index = -1; - DWORD mask, tibidx; - int i; - - if (tls_storage == NULL) - { - - APIRET rc; - - /* allocate memory for TLS storage */ - rc = DosAllocThreadLocalMemory( 1, &tls_storage); - if (rc) - fprintf( stderr, "DosAllocThreadLocalMemory error: return code = %u\n", - rc); - /* create a mutex */ - if (pthread_mutex_init( &tls_mutex, NULL)) - fprintf( stderr, "Failed to init TLS mutex\n"); - } - - pthread_mutex_lock( &tls_mutex); - - tibidx = 0; - if (tls_bits[0] == 0xFFFFFFFF) - { - if (tls_bits[1] == 0xFFFFFFFF) - { - fprintf( stderr, "tid#%d, no more TLS bits available\n", _threadid); - pthread_mutex_unlock( &tls_mutex); - return -1; - } - tibidx = 1; - } - - for (i=0; i<32; i++) - { - mask = (1 << i); - if ((tls_bits[ tibidx] & mask) == 0) - { - tls_bits[ tibidx] |= mask; - index = (tibidx*32) + i; - break; - } - } - tls_storage[index] = 0; - - pthread_mutex_unlock( &tls_mutex); - /* fprintf( stderr, "tid#%d, TlsAlloc index %d\n", _threadid, index); */ - return index; -} - -BOOL TlsFree( DWORD index) -{ - int tlsidx; - DWORD mask; - - if (index >= TLS_MINIMUM_AVAILABLE) - return NULL; - - pthread_mutex_lock( &tls_mutex); - - tlsidx = 0; - if (index > 32) - tlsidx++; - - mask = (1 << index); - if (tls_bits[ tlsidx] & mask) - { - tls_bits[tlsidx] &= ~mask; - tls_storage[index] = 0; - pthread_mutex_unlock( &tls_mutex); - return TRUE; - } - - pthread_mutex_unlock( &tls_mutex); - return FALSE; -} - - -PVOID TlsGetValue( DWORD index) -{ - if (index >= TLS_MINIMUM_AVAILABLE) - return NULL; - - /* verify if memory has been allocated for this thread */ - if (*tls_storage == NULL) - { - /* allocate memory for indexes */ - *tls_storage = (ULONG)calloc( TLS_MINIMUM_AVAILABLE, sizeof(int)); - /* fprintf(stderr, "tid#%d, tls_storage %x\n", _threadid, *tls_storage); */ - } - - ULONG* tls_array = (ULONG*) *tls_storage; - return (PVOID) tls_array[index]; -} - - -BOOL TlsSetValue( DWORD index, PVOID val) -{ - - /* verify if memory has been allocated for this thread */ - if (*tls_storage == NULL) - { - /* allocate memory for indexes */ - *tls_storage = (ULONG)calloc( TLS_MINIMUM_AVAILABLE, sizeof(int)); - /* fprintf(stderr, "tid#%d, tls_storage %x\n", _threadid, *tls_storage); */ - } - - if (index >= TLS_MINIMUM_AVAILABLE) - return FALSE; - - ULONG* tls_array = (ULONG*) *tls_storage; - /* fprintf( stderr, "tid#%d, TlsSetValue array %08x index %d -> %08x (old)\n", _threadid, tls_array, index, tls_array[ index]); */ - tls_array[ index] = (ULONG) val; - /* fprintf( stderr, "tid#%d, TlsSetValue array %08x index %d -> %08x\n", _threadid, tls_array, index, val); */ - return TRUE; -} diff --git a/mysys/my_pread.c b/mysys/my_pread.c index 2d42a6ebbc4..7a09c21e039 100644 --- a/mysys/my_pread.c +++ b/mysys/my_pread.c @@ -26,7 +26,7 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, myf MyFlags) { uint readbytes; - int error; + int error= 0; DBUG_ENTER("my_pread"); DBUG_PRINT("my",("Fd: %d Seek: %lu Buffer: 0x%lx Count: %u MyFlags: %d", Filedes, (ulong) offset, (long) Buffer, Count, MyFlags)); @@ -37,17 +37,40 @@ uint my_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, errno=0; /* Linux doesn't reset this */ #endif #ifndef HAVE_PREAD + off_t old_offset; + pthread_mutex_lock(&my_file_info[Filedes].mutex); - readbytes= (uint) -1; - error= (lseek(Filedes, offset, MY_SEEK_SET) == -1L || - (readbytes = (uint) read(Filedes, Buffer, Count)) != Count); + /* + As we cannot change the file pointer, we save the old position, + before seeking to the given offset + */ + + error= (old_offset= (off_t)lseek(Filedes, 0L, MY_SEEK_CUR)) == -1L || + lseek(Filedes, offset, MY_SEEK_SET) == -1L; + + if (!error) /* Seek was successful */ + { + if ((readbytes = (uint) read(Filedes, Buffer, Count)) == -1L) + my_errno= errno; + + /* + We should seek back, even if read failed. If this fails, + we will return an error. If read failed as well, we will + save the errno from read, not from lseek(). + */ + if ((error= (lseek(Filedes, old_offset, MY_SEEK_SET) == -1L)) && + readbytes != -1L) + my_errno= errno; + } + pthread_mutex_unlock(&my_file_info[Filedes].mutex); #else - error=((readbytes = (uint) pread(Filedes, Buffer, Count, offset)) != Count); + if ((error= ((readbytes = + (uint) pread(Filedes, Buffer, Count, offset)) != Count))) + my_errno= errno; #endif - if (error) + if (error || readbytes != Count) { - my_errno=errno; DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d", (int) readbytes, Count,Filedes,my_errno)); #ifdef THREAD @@ -92,17 +115,41 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, for (;;) { #ifndef HAVE_PREAD - int error; + int error= 0; + off_t old_offset; writenbytes= (uint) -1; pthread_mutex_lock(&my_file_info[Filedes].mutex); - error=(lseek(Filedes, offset, MY_SEEK_SET) != -1L && - (writenbytes = (uint) write(Filedes, Buffer, Count)) == Count); + + /* + As we cannot change the file pointer, we save the old position, + before seeking to the given offset + */ + error= ((old_offset= (off_t)lseek(Filedes, 0L, MY_SEEK_CUR)) == -1L || + lseek(Filedes, offset, MY_SEEK_SET) == -1L); + + if (!error) /* Seek was successful */ + { + if ((writenbytes = (uint) write(Filedes, Buffer, Count)) == -1L) + my_errno= errno; + + /* + We should seek back, even if write failed. If this fails, + we will return an error. If write failed as well, we will + save the errno from write, not from lseek(). + */ + if ((error= (lseek(Filedes, old_offset, MY_SEEK_SET) == -1L)) && + writenbytes != -1L) + my_errno= errno; + } pthread_mutex_unlock(&my_file_info[Filedes].mutex); - if (error) + + if (!error && writenbytes == Count) break; #else if ((writenbytes = (uint) pwrite(Filedes, Buffer, Count,offset)) == Count) break; + else + my_errno= errno; #endif if ((int) writenbytes != -1) { /* Safegueard */ @@ -111,7 +158,6 @@ uint my_pwrite(int Filedes, const byte *Buffer, uint Count, my_off_t offset, Count-=writenbytes; offset+=writenbytes; } - my_errno=errno; DBUG_PRINT("error",("Write only %d bytes",writenbytes)); #ifndef NO_BACKGROUND #ifdef THREAD diff --git a/mysys/my_pthread.c b/mysys/my_pthread.c index fe3480ea10f..844112991f6 100644 --- a/mysys/my_pthread.c +++ b/mysys/my_pthread.c @@ -23,7 +23,7 @@ #include <m_string.h> #include <thr_alarm.h> -#if (defined(__BSD__) || defined(_BSDI_VERSION)) && !defined(HAVE_mit_thread) +#if (defined(__BSD__) || defined(_BSDI_VERSION)) #define SCHED_POLICY SCHED_RR #else #define SCHED_POLICY SCHED_OTHER @@ -75,9 +75,6 @@ void my_pthread_attr_setprio(pthread_attr_t *attr, int priority) #ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC #undef pthread_getspecific -#ifdef HAVE_UNIXWARE7_THREADS -#define pthread_getspecific thr_getspecific -#endif void *my_pthread_getspecific_imp(pthread_key_t key) { @@ -189,7 +186,7 @@ struct tm *gmtime_r(const time_t *clock, struct tm *res) ** Author: Gary Wisniewski <garyw@spidereye.com.au>, much modified by Monty ****************************************************************************/ -#if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(sigwait) && !defined(__WIN__) && !defined(HAVE_rts_threads) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(OS2) +#if !defined(HAVE_SIGWAIT) && !defined(sigwait) && !defined(__WIN__) && !defined(HAVE_rts_threads) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) #if !defined(DONT_USE_SIGSUSPEND) @@ -428,7 +425,7 @@ int sigwait(sigset_t *setp, int *sigp) ** Patches for AIX and DEC OSF/1 3.2 *****************************************************************************/ -#if (defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) && !defined(HAVE_UNIXWARE7_THREADS)) || defined(HAVE_DEC_3_2_THREADS) +#if defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) #include <netdb.h> diff --git a/mysys/my_redel.c b/mysys/my_redel.c index 1e3cfceb495..606d301e1d0 100644 --- a/mysys/my_redel.c +++ b/mysys/my_redel.c @@ -13,7 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES /* sys/types is included */ #include "mysys_priv.h" #include <my_dir.h> #include <m_string.h> @@ -89,14 +88,14 @@ int my_copystat(const char *from, const char *to, int MyFlags) return 1; VOID(chmod(to, statbuf.st_mode & 07777)); /* Copy modes */ -#if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__) +#if !defined(__WIN__) && !defined(__NETWARE__) if (statbuf.st_nlink > 1 && MyFlags & MY_LINK_WARNING) { if (MyFlags & MY_LINK_WARNING) my_error(EE_LINK_WARNING,MYF(ME_BELL+ME_WAITTANG),from,statbuf.st_nlink); } VOID(chown(to, statbuf.st_uid, statbuf.st_gid)); /* Copy ownership */ -#endif /* MSDOS */ +#endif /* !__WIN__ && !__NETWARE__ */ #ifndef VMS #ifndef __ZTC__ diff --git a/mysys/my_rename.c b/mysys/my_rename.c index c4aeb95b2c0..6a6aa6a5796 100644 --- a/mysys/my_rename.c +++ b/mysys/my_rename.c @@ -13,7 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define USES_TYPES #include "mysys_priv.h" #include <my_dir.h> #include "mysys_err.h" diff --git a/mysys/my_seek.c b/mysys/my_seek.c index fd2344e0d36..e59e205b5f3 100644 --- a/mysys/my_seek.c +++ b/mysys/my_seek.c @@ -43,7 +43,7 @@ my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags __attribute__((unused))) { - reg1 os_off_t newpos; + reg1 os_off_t newpos= -1; DBUG_ENTER("my_seek"); DBUG_PRINT("my",("Fd: %d Hpos: %lu Pos: %lu Whence: %d MyFlags: %d", fd, (ulong) (((ulonglong) pos) >> 32), (ulong) pos, diff --git a/mysys/my_sleep.c b/mysys/my_sleep.c index 50e6fae17fc..87170e4af41 100644 --- a/mysys/my_sleep.c +++ b/mysys/my_sleep.c @@ -24,8 +24,6 @@ void my_sleep(ulong m_seconds) delay(m_seconds/1000+1); #elif defined(__WIN__) Sleep(m_seconds/1000+1); /* Sleep() has millisecond arg */ -#elif defined(OS2) - DosSleep(m_seconds/1000+1); #elif defined(HAVE_SELECT) struct timeval t; t.tv_sec= m_seconds / 1000000L; diff --git a/mysys/my_static.c b/mysys/my_static.c index 694e5058bb0..95521c49ab7 100644 --- a/mysys/my_static.c +++ b/mysys/my_static.c @@ -18,7 +18,7 @@ a shared library */ -#if !defined(stdin) || defined(OS2) +#if !defined(stdin) #include "mysys_priv.h" #include "my_static.h" #include "my_alarm.h" @@ -91,13 +91,6 @@ struct st_irem *sf_malloc_root = NULL; int volatile my_have_got_alarm=0; /* declare variable to reset */ ulong my_time_to_wait_for_lock=2; /* In seconds */ - /* - We need to have this define here as otherwise linking will fail - on OSF1 when compiling --without-raid --with-debug - */ - -const char *raid_type_string[]={"none","striped"}; - /* from errors.c */ #ifdef SHARED_LIBRARY char * NEAR globerrs[GLOBERRS]; /* my_error_messages is here */ diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index 2ad08ef67de..279672be11c 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -33,9 +33,11 @@ File my_create_with_symlink(const char *linkname, const char *filename, int create_link; char abs_linkname[FN_REFLEN]; DBUG_ENTER("my_create_with_symlink"); + DBUG_PRINT("enter", ("linkname: %s filename: %s", linkname, filename)); if (my_disable_symlinks) { + DBUG_PRINT("info", ("Symlinks disabled")); /* Create only the file, not the link and file */ create_link= 0; if (linkname) diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index b44e5ced99f..d83aa95b0ef 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -269,12 +269,12 @@ void my_thread_end(void) tmp->dbug=0; } #endif -#if !defined(__bsdi__) && !defined(__OpenBSD__) || defined(HAVE_mit_thread) +#if !defined(__bsdi__) && !defined(__OpenBSD__) /* bsdi and openbsd 3.5 dumps core here */ pthread_cond_destroy(&tmp->suspend); #endif pthread_mutex_destroy(&tmp->mutex); -#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) +#if !defined(__WIN__) || defined(USE_TLS) free(tmp); #else tmp->init= 0; @@ -293,7 +293,7 @@ void my_thread_end(void) pthread_mutex_unlock(&THR_LOCK_threads); } /* The following free has to be done, even if my_thread_var() is 0 */ -#if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS) +#if !defined(__WIN__) || defined(USE_TLS) pthread_setspecific(THR_KEY_mysys,0); #endif } @@ -324,7 +324,7 @@ long my_thread_id() { #if defined(HAVE_PTHREAD_GETSEQUENCE_NP) return pthread_getsequence_np(pthread_self()); -#elif (defined(__sun) || defined(__sgi) || defined(__linux__)) && !defined(HAVE_mit_thread) +#elif (defined(__sun) || defined(__sgi) || defined(__linux__)) return pthread_self(); #else return my_thread_var->id; diff --git a/mysys/my_vle.c b/mysys/my_vle.c new file mode 100644 index 00000000000..5b93ba69bd9 --- /dev/null +++ b/mysys/my_vle.c @@ -0,0 +1,112 @@ +/* + Copyright (C) 2005 MySQL AB + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA +*/ + +/* + Variable length encoding. + + A method to store an arbitrary-size non-negative integer. We let the + most significant bit of the number indicate that the next byte + should be contatenated to form the real number. +*/ + +#include "my_vle.h" + +/* + Function to encode an unsigned long as VLE. The bytes for the VLE + will be written to the location pointed to by 'out'. The maximum + number of bytes written will be 'max'. + + PARAMETERS + + out Pointer to beginning of where to store VLE bytes. + max Maximum number of bytes to write. + n Number to encode. + + RETURN VALUE + On success, one past the end of the array containing the VLE + bytes. On failure, the 'out' pointer is returned. +*/ + +byte* +my_vle_encode(byte* out, my_size_t max, ulong n) +{ + byte buf[my_vle_sizeof(n)]; + byte *ptr= buf; + my_size_t len; + + do + { + *ptr++= (byte) (n & 0x7F); + n>>= 7; + } + while (n > 0); + + len= ptr - buf; + + if (len <= max) + { + /* + The bytes are stored in reverse order in 'buf'. Let's write them + in correct order to the output buffer and set the MSB at the + same time. + */ + while (ptr-- > buf) + { + byte v= *ptr; + if (ptr > buf) + v|= 0x80; + *out++= v; + } + } + + return out; +} + +/* + Function to decode a VLE representation of an integral value. + + + PARAMETERS + + result_ptr Pointer to an unsigned long where the value will be written. + vle Pointer to the VLE bytes. + + RETURN VALUE + + One-past the end of the VLE bytes. The routine will never read + more than sizeof(*result_ptr) + 1 bytes. +*/ + +byte const* +my_vle_decode(ulong *result_ptr, byte const *vle) +{ + ulong result= 0; + my_size_t cnt= 1; + + do + { + result<<= 7; + result|= (*vle & 0x7F); + } + while ((*vle++ & 0x80) && ++cnt <= sizeof(*result_ptr) + 1); + + if (cnt <= sizeof(*result_ptr) + 1) + *result_ptr= result; + + return vle; +} diff --git a/mysys/mysys_priv.h b/mysys/mysys_priv.h index 8a636e94626..709cfed969a 100644 --- a/mysys/mysys_priv.h +++ b/mysys/mysys_priv.h @@ -40,3 +40,5 @@ extern pthread_mutex_t THR_LOCK_charset; #ifndef EDQUOT #define EDQUOT (-1) #endif + +void my_error_unregister_all(void); diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c index a3bc3702c34..96c56645e94 100644 --- a/mysys/ptr_cmp.c +++ b/mysys/ptr_cmp.c @@ -184,7 +184,7 @@ my_off_t my_get_ptr(byte *ptr, uint pack_length) case 4: pos= (my_off_t) mi_uint4korr(ptr); break; case 3: pos= (my_off_t) mi_uint3korr(ptr); break; case 2: pos= (my_off_t) mi_uint2korr(ptr); break; - case 1: pos= (my_off_t) mi_uint2korr(ptr); break; + case 1: pos= (my_off_t) *(uchar*) ptr; break; default: DBUG_ASSERT(0); } return pos; diff --git a/mysys/queues.c b/mysys/queues.c index 7809c97131c..5970922284f 100644 --- a/mysys/queues.c +++ b/mysys/queues.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000, 2005 MySQL AB 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 @@ -16,6 +16,10 @@ /* Code for generell handling of priority Queues. Implemention of queues from "Algoritms in C" by Robert Sedgewick. + An optimisation of _downheap suggested in Exercise 7.51 in "Data + Structures & Algorithms in C++" by Mark Allen Weiss, Second Edition + was implemented by Mikael Ronstrom 2005. Also the O(N) algorithm + of queue_fix was implemented. */ #include "mysys_priv.h" @@ -62,6 +66,46 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, } + +/* + Init queue, uses init_queue internally for init work but also accepts + auto_extent as parameter + + SYNOPSIS + init_queue_ex() + queue Queue to initialise + max_elements Max elements that will be put in queue + offset_to_key Offset to key in element stored in queue + Used when sending pointers to compare function + max_at_top Set to 1 if you want biggest element on top. + compare Compare function for elements, takes 3 arguments. + first_cmp_arg First argument to compare function + auto_extent When the queue is full and there is insert operation + extend the queue. + + NOTES + Will allocate max_element pointers for queue array + + RETURN + 0 ok + 1 Could not allocate memory +*/ + +int init_queue_ex(QUEUE *queue, uint max_elements, uint offset_to_key, + pbool max_at_top, int (*compare) (void *, byte *, byte *), + void *first_cmp_arg, uint auto_extent) +{ + int ret; + DBUG_ENTER("init_queue_ex"); + + if ((ret= init_queue(queue, max_elements, offset_to_key, max_at_top, compare, + first_cmp_arg))) + DBUG_RETURN(ret); + + queue->auto_extent= auto_extent; + DBUG_RETURN(0); +} + /* Reinitialize queue for other usage @@ -181,6 +225,31 @@ void queue_insert(register QUEUE *queue, byte *element) queue->root[idx]= element; } +/* + Does safe insert. If no more space left on the queue resize it. + Return codes: + 0 - OK + 1 - Cannot allocate more memory + 2 - auto_extend is 0, the operation would + +*/ + +int queue_insert_safe(register QUEUE *queue, byte *element) +{ + + if (queue->elements == queue->max_elements) + { + if (!queue->auto_extent) + return 2; + else if (resize_queue(queue, queue->max_elements + queue->auto_extent)) + return 1; + } + + queue_insert(queue, element); + return 0; +} + + /* Remove item from queue */ /* Returns pointer to removed element */ @@ -203,8 +272,64 @@ void queue_replaced(QUEUE *queue) } #endif - /* Fix heap when index have changed */ +#ifndef OLD_VERSION + +void _downheap(register QUEUE *queue, uint idx) +{ + byte *element; + uint elements,half_queue,offset_to_key, next_index; + bool first= TRUE; + uint start_idx= idx; + + offset_to_key=queue->offset_to_key; + element=queue->root[idx]; + half_queue=(elements=queue->elements) >> 1; + + while (idx <= half_queue) + { + int cmp; + next_index=idx+idx; + if (next_index < elements && + (queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + queue->root[next_index+1]+offset_to_key) ^ + queue->max_at_top) > 0) + next_index++; + if (first && + (((cmp=queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + element+offset_to_key)) == 0) || + ((cmp ^ queue->max_at_top) > 0))) + { + queue->root[idx]= element; + return; + } + queue->root[idx]=queue->root[next_index]; + idx=next_index; + first= FALSE; + } + + next_index= idx >> 1; + while (next_index > start_idx) + { + if ((queue->compare(queue->first_cmp_arg, + queue->root[next_index]+offset_to_key, + element+offset_to_key) ^ + queue->max_at_top) < 0) + break; + queue->root[idx]=queue->root[next_index]; + idx=next_index; + next_index= idx >> 1; + } + queue->root[idx]=element; +} +#else + /* + The old _downheap version is kept for comparisons with the benchmark + suit or new benchmarks anyone wants to run for comparisons. + */ + /* Fix heap when index have changed */ void _downheap(register QUEUE *queue, uint idx) { byte *element; @@ -236,20 +361,336 @@ void _downheap(register QUEUE *queue, uint idx) } -static int queue_fix_cmp(QUEUE *queue, void **a, void **b) -{ - return queue->compare(queue->first_cmp_arg, - (byte*) (*a)+queue->offset_to_key, - (byte*) (*b)+queue->offset_to_key); -} +#endif /* - Fix heap when every element was changed, - actually, it can be done better, in linear time, not in n*log(n) + Fix heap when every element was changed. */ void queue_fix(QUEUE *queue) { - qsort2(queue->root+1,queue->elements, sizeof(void *), - (qsort2_cmp)queue_fix_cmp, queue); + uint i; + for (i= queue->elements >> 1; i > 0; i--) + _downheap(queue, i); +} + +#ifdef MAIN + /* + A test program for the priority queue implementation. + It can also be used to benchmark changes of the implementation + Build by doing the following in the directory mysys + make test_priority_queue + ./test_priority_queue + + Written by Mikael Ronström, 2005 + */ + +static uint num_array[1025]; +static uint tot_no_parts= 0; +static uint tot_no_loops= 0; +static uint expected_part= 0; +static uint expected_num= 0; +static bool max_ind= 0; +static bool fix_used= 0; +static ulonglong start_time= 0; + +static bool is_divisible_by(uint num, uint divisor) +{ + uint quotient= num / divisor; + if (quotient * divisor == num) + return TRUE; + return FALSE; +} + +void calculate_next() +{ + uint part= expected_part, num= expected_num; + uint no_parts= tot_no_parts; + if (max_ind) + { + do + { + while (++part <= no_parts) + { + if (is_divisible_by(num, part) && + (num <= ((1 << 21) + part))) + { + expected_part= part; + expected_num= num; + return; + } + } + part= 0; + } while (--num); + } + else + { + do + { + while (--part > 0) + { + if (is_divisible_by(num, part)) + { + expected_part= part; + expected_num= num; + return; + } + } + part= no_parts + 1; + } while (++num); + } +} + +void calculate_end_next(uint part) +{ + uint no_parts= tot_no_parts, num; + num_array[part]= 0; + if (max_ind) + { + expected_num= 0; + for (part= no_parts; part > 0 ; part--) + { + if (num_array[part]) + { + num= num_array[part] & 0x3FFFFF; + if (num >= expected_num) + { + expected_num= num; + expected_part= part; + } + } + } + if (expected_num == 0) + expected_part= 0; + } + else + { + expected_num= 0xFFFFFFFF; + for (part= 1; part <= no_parts; part++) + { + if (num_array[part]) + { + num= num_array[part] & 0x3FFFFF; + if (num <= expected_num) + { + expected_num= num; + expected_part= part; + } + } + } + if (expected_num == 0xFFFFFFFF) + expected_part= 0; + } + return; +} +static int test_compare(void *null_arg, byte *a, byte *b) +{ + uint a_num= (*(uint*)a) & 0x3FFFFF; + uint b_num= (*(uint*)b) & 0x3FFFFF; + uint a_part, b_part; + if (a_num > b_num) + return +1; + if (a_num < b_num) + return -1; + a_part= (*(uint*)a) >> 22; + b_part= (*(uint*)b) >> 22; + if (a_part < b_part) + return +1; + if (a_part > b_part) + return -1; + return 0; +} + +bool check_num(uint num_part) +{ + uint part= num_part >> 22; + uint num= num_part & 0x3FFFFF; + if (part == expected_part) + if (num == expected_num) + return FALSE; + printf("Expect part %u Expect num 0x%x got part %u num 0x%x max_ind %u fix_used %u \n", + expected_part, expected_num, part, num, max_ind, fix_used); + return TRUE; +} + + +void perform_insert(QUEUE *queue) +{ + uint i= 1, no_parts= tot_no_parts; + uint backward_start= 0; + + expected_part= 1; + expected_num= 1; + + if (max_ind) + backward_start= 1 << 21; + + do + { + uint num= (i + backward_start); + if (max_ind) + { + while (!is_divisible_by(num, i)) + num--; + if (max_ind && (num > expected_num || + (num == expected_num && i < expected_part))) + { + expected_num= num; + expected_part= i; + } + } + num_array[i]= num + (i << 22); + if (fix_used) + queue_element(queue, i-1)= (byte*)&num_array[i]; + else + queue_insert(queue, (byte*)&num_array[i]); + } while (++i <= no_parts); + if (fix_used) + { + queue->elements= no_parts; + queue_fix(queue); + } +} + +bool perform_ins_del(QUEUE *queue, bool max_ind) +{ + uint i= 0, no_loops= tot_no_loops, j= tot_no_parts; + do + { + uint num_part= *(uint*)queue_top(queue); + uint part= num_part >> 22; + if (check_num(num_part)) + return TRUE; + if (j++ >= no_loops) + { + calculate_end_next(part); + queue_remove(queue, (uint) 0); + } + else + { + calculate_next(); + if (max_ind) + num_array[part]-= part; + else + num_array[part]+= part; + queue_top(queue)= (byte*)&num_array[part]; + queue_replaced(queue); + } + } while (++i < no_loops); + return FALSE; +} + +bool do_test(uint no_parts, uint l_max_ind, bool l_fix_used) +{ + QUEUE queue; + bool result; + max_ind= l_max_ind; + fix_used= l_fix_used; + init_queue(&queue, no_parts, 0, max_ind, test_compare, NULL); + tot_no_parts= no_parts; + tot_no_loops= 1024; + perform_insert(&queue); + if ((result= perform_ins_del(&queue, max_ind))) + delete_queue(&queue); + if (result) + { + printf("Error\n"); + return TRUE; + } + return FALSE; +} + +static void start_measurement() +{ + start_time= my_getsystime(); } + +static void stop_measurement() +{ + ulonglong stop_time= my_getsystime(); + uint time_in_micros; + stop_time-= start_time; + stop_time/= 10; /* Convert to microseconds */ + time_in_micros= (uint)stop_time; + printf("Time expired is %u microseconds \n", time_in_micros); +} + +static void benchmark_test() +{ + QUEUE queue_real; + QUEUE *queue= &queue_real; + uint i, add; + fix_used= TRUE; + max_ind= FALSE; + tot_no_parts= 1024; + init_queue(queue, tot_no_parts, 0, max_ind, test_compare, NULL); + /* + First benchmark whether queue_fix is faster than using queue_insert + for sizes of 16 partitions. + */ + for (tot_no_parts= 2, add=2; tot_no_parts < 128; + tot_no_parts+= add, add++) + { + printf("Start benchmark queue_fix, tot_no_parts= %u \n", tot_no_parts); + start_measurement(); + for (i= 0; i < 128; i++) + { + perform_insert(queue); + queue_remove_all(queue); + } + stop_measurement(); + + fix_used= FALSE; + printf("Start benchmark queue_insert\n"); + start_measurement(); + for (i= 0; i < 128; i++) + { + perform_insert(queue); + queue_remove_all(queue); + } + stop_measurement(); + } + /* + Now benchmark insertion and deletion of 16400 elements. + Used in consecutive runs this shows whether the optimised _downheap + is faster than the standard implementation. + */ + printf("Start benchmarking _downheap \n"); + start_measurement(); + perform_insert(queue); + for (i= 0; i < 65536; i++) + { + uint num, part; + num= *(uint*)queue_top(queue); + num+= 16; + part= num >> 22; + num_array[part]= num; + queue_top(queue)= (byte*)&num_array[part]; + queue_replaced(queue); + } + for (i= 0; i < 16; i++) + queue_remove(queue, (uint) 0); + queue_remove_all(queue); + stop_measurement(); +} + +int main() +{ + int i, add= 1; + for (i= 1; i < 1024; i+=add, add++) + { + printf("Start test for priority queue of size %u\n", i); + if (do_test(i, 0, 1)) + return -1; + if (do_test(i, 1, 1)) + return -1; + if (do_test(i, 0, 0)) + return -1; + if (do_test(i, 1, 0)) + return -1; + } + benchmark_test(); + printf("OK\n"); + return 0; +} +#endif diff --git a/mysys/raid.cc b/mysys/raid.cc deleted file mode 100644 index c70c01fde4b..00000000000 --- a/mysys/raid.cc +++ /dev/null @@ -1,798 +0,0 @@ -/* Copyright (C) 2000 MySQL AB - - 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -/* - - RAID support for MySQL. Raid 0 (stiping) only implemented yet. - - Why RAID? Why it must be in MySQL? - - This is because then you can: - 1. Have bigger tables than your OS limit. In time of writing this - we are hitting to 2GB limit under linux/ext2 - 2. You can get more speed from IO bottleneck by putting - Raid dirs on different physical disks. - 3. Getting more fault tolerance (not implemented yet) - - Why not to use RAID: - - 1. You are losing some processor power to calculate things, - do more syscalls and interrupts. - - Functionality is supplied by two classes: RaidFd and RaidName. - RaidFd supports funtionality over file descriptors like - open/create/write/seek/close. RaidName supports functionality - like rename/delete where we have no relations to filedescriptors. - RaidName can be prorably unchanged for different Raid levels. RaidFd - have to be virtual I think ;). - You can speed up some calls in MySQL code by skipping RAID code. - For example LOAD DATA INFILE never needs to read RAID-ed files. - This can be done adding proper "#undef my_read" or similar undef-s - in your code. Check out the raid.h! - - Some explanation about _seek_vector[] - This is seek cache. RAID seeks too much and we cacheing this. We - fool it and just storing new position in file to _seek_vector. - When there is no seeks to do, we are putting RAID_SEEK_DONE into it. - Any other value requires seeking to that position. - - TODO: - - - - Implement other fancy things like RAID 1 (mirroring) and RAID 5. - Should not to be very complex. - - - Optimize big blob writes by resorting write buffers and writing - big chunks at once instead of doing many syscalls. - after thinking I - found this is useless. This is because same thing one can do with just - increasing RAID_CHUNKSIZE. Monty, what do you think? tonu. - - - If needed, then implement missing syscalls. One known to miss is stat(); - - - Make and use a thread safe dynamic_array buffer. The used one - will not work if needs to be extended at the same time someone is - accessing it. - - - tonu@mysql.com & monty@mysql.com -*/ - -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - -#include "mysys_priv.h" -#include <my_dir.h> -#include <m_string.h> -#include <assert.h> - -#if defined(USE_RAID) && !defined(MYSQL_CLIENT) - -#define RAID_SEEK_DONE ~(off_t) 0 -#define RAID_SIZE_UNKNOWN ~(my_off_t) 0 - -DYNAMIC_ARRAY RaidFd::_raid_map; - - -/* --------------- C compatibility ---------------*/ - -extern "C" { - - void init_raid(void) - { - /* Allocate memory for global file to raid map */ - my_init_dynamic_array(&RaidFd::_raid_map, sizeof(RaidFd*), 4096, 1024); - } - void end_raid(void) - { - /* Free memory used by raid */ - delete_dynamic(&RaidFd::_raid_map); - } - - bool is_raid(File fd) - { - return RaidFd::IsRaid(fd); - } - - File my_raid_create(const char *FileName, int CreateFlags, int access_flags, - uint raid_type, uint raid_chunks, ulong raid_chunksize, - myf MyFlags) - { - DBUG_ENTER("my_raid_create"); - DBUG_PRINT("enter",("Filename: %s CreateFlags: %d access_flags: %d MyFlags: %d", - FileName, CreateFlags, access_flags, MyFlags)); - if (raid_type) - { - RaidFd *raid = new RaidFd(raid_type, raid_chunks , raid_chunksize); - File res = raid->Create(FileName,CreateFlags,access_flags,MyFlags); - if (res < 0 || set_dynamic(&RaidFd::_raid_map,(char*) &raid,res)) - { - delete raid; - DBUG_RETURN(-1); - } - DBUG_RETURN(res); - } - else - DBUG_RETURN(my_create(FileName, CreateFlags, access_flags, MyFlags)); - } - - File my_raid_open(const char *FileName, int Flags, - uint raid_type, uint raid_chunks, ulong raid_chunksize, - myf MyFlags) - { - DBUG_ENTER("my_raid_open"); - DBUG_PRINT("enter",("Filename: %s Flags: %d MyFlags: %d", - FileName, Flags, MyFlags)); - if (raid_type) - { - RaidFd *raid = new RaidFd(raid_type, raid_chunks , raid_chunksize); - File res = raid->Open(FileName,Flags,MyFlags); - if (res < 0 || set_dynamic(&RaidFd::_raid_map,(char*) &raid,res)) - { - delete raid; - DBUG_RETURN(-1); - } - DBUG_RETURN(res); - } - else - DBUG_RETURN(my_open(FileName, Flags, MyFlags)); - } - - my_off_t my_raid_seek(File fd, my_off_t pos,int whence,myf MyFlags) - { - DBUG_ENTER("my_raid_seek"); - DBUG_PRINT("enter",("Fd: %d pos: %lu whence: %d MyFlags: %d", - fd, (ulong) pos, whence, MyFlags)); - - if (is_raid(fd)) - { - assert(pos != MY_FILEPOS_ERROR); - - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Seek(pos,whence,MyFlags)); - } - else - DBUG_RETURN(my_seek(fd, pos, whence, MyFlags)); - } - - my_off_t my_raid_tell(File fd,myf MyFlags) - { - DBUG_ENTER("my_raid_tell"); - DBUG_PRINT("enter",("Fd: %d MyFlags: %d", - fd, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Tell(MyFlags)); - } - else - DBUG_RETURN(my_tell(fd, MyFlags)); - } - - uint my_raid_write(File fd,const byte *Buffer, uint Count, myf MyFlags) - { - DBUG_ENTER("my_raid_write"); - DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d", - fd, Buffer, Count, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Write(Buffer,Count,MyFlags)); - } else - DBUG_RETURN(my_write(fd,Buffer,Count,MyFlags)); - } - - uint my_raid_read(File fd, byte *Buffer, uint Count, myf MyFlags) - { - DBUG_ENTER("my_raid_read"); - DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d", - fd, Buffer, Count, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Read(Buffer,Count,MyFlags)); - } else - DBUG_RETURN(my_read(fd,Buffer,Count,MyFlags)); - } - - uint my_raid_pread(File Filedes, byte *Buffer, uint Count, my_off_t offset, - myf MyFlags) - { - DBUG_ENTER("my_raid_pread"); - DBUG_PRINT("enter", - ("Fd: %d Buffer: 0x%lx Count: %u offset: %u MyFlags: %d", - Filedes, Buffer, Count, offset, MyFlags)); - if (is_raid(Filedes)) - { - assert(offset != MY_FILEPOS_ERROR); - - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,Filedes,RaidFd**)); - /* Returning value isn't important because real seek is done later. */ - raid->Seek(offset,MY_SEEK_SET,MyFlags); - DBUG_RETURN(raid->Read(Buffer,Count,MyFlags)); - } - else - DBUG_RETURN(my_pread(Filedes, Buffer, Count, offset, MyFlags)); - } - - uint my_raid_pwrite(int Filedes, const byte *Buffer, uint Count, - my_off_t offset, myf MyFlags) - { - DBUG_ENTER("my_raid_pwrite"); - DBUG_PRINT("enter", - ("Fd: %d Buffer: 0x %lx Count: %u offset: %u MyFlags: %d", - Filedes, Buffer, Count, offset, MyFlags)); - if (is_raid(Filedes)) - { - assert(offset != MY_FILEPOS_ERROR); - - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,Filedes,RaidFd**)); - /* Returning value isn't important because real seek is done later. */ - raid->Seek(offset,MY_SEEK_SET,MyFlags); - DBUG_RETURN(raid->Write(Buffer,Count,MyFlags)); - } - else - DBUG_RETURN(my_pwrite(Filedes, Buffer, Count, offset, MyFlags)); - } - - int my_raid_lock(File fd, int locktype, my_off_t start, my_off_t length, - myf MyFlags) - { - DBUG_ENTER("my_raid_lock"); - DBUG_PRINT("enter",("Fd: %d start: %u length: %u MyFlags: %d", - fd, start, length, MyFlags)); - if (my_disable_locking) - DBUG_RETURN(0); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Lock(locktype, start, length, MyFlags)); - } - else - DBUG_RETURN(my_lock(fd, locktype, start, length, MyFlags)); - } - - int my_raid_close(File fd, myf MyFlags) - { - DBUG_ENTER("my_raid_close"); - DBUG_PRINT("enter",("Fd: %d MyFlags: %d", - fd, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - RaidFd *tmp=0; - set_dynamic(&RaidFd::_raid_map,(char*) &tmp,fd); - int res = raid->Close(MyFlags); - delete raid; - DBUG_RETURN(res); - } - else - DBUG_RETURN(my_close(fd, MyFlags)); - } - - int my_raid_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) - { - DBUG_ENTER("my_raid_chsize"); - DBUG_PRINT("enter",("Fd: %d newlength: %u MyFlags: %d", - fd, newlength, MyFlags)); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Chsize(fd, newlength, filler, MyFlags)); - } - else - DBUG_RETURN(my_chsize(fd, newlength, filler, MyFlags)); - } - - int my_raid_rename(const char *from, const char *to, - uint raid_chunks, myf MyFlags) - { - char from_tmp[FN_REFLEN]; - char to_tmp[FN_REFLEN]; - DBUG_ENTER("my_raid_rename"); - - uint from_pos = dirname_length(from); - uint to_pos = dirname_length(to); - memcpy(from_tmp, from, from_pos); - memcpy(to_tmp, to, to_pos); - for (uint i = 0 ; i < raid_chunks ; i++ ) - { - sprintf(from_tmp+from_pos,"%02x/%s", i, from + from_pos); - sprintf(to_tmp+to_pos,"%02x/%s", i, to+ to_pos); - /* Convert if not unix */ - unpack_filename(from_tmp, from_tmp); - unpack_filename(to_tmp,to_tmp); - if (my_rename(from_tmp, to_tmp, MyFlags)) - DBUG_RETURN(-1); - } - DBUG_RETURN(0); - } - - int my_raid_delete(const char *from, uint raid_chunks, myf MyFlags) - { - char from_tmp[FN_REFLEN]; - uint from_pos = dirname_length(from); - DBUG_ENTER("my_raid_delete"); - - if (!raid_chunks) - DBUG_RETURN(my_delete(from,MyFlags)); - for (uint i = 0 ; i < raid_chunks ; i++ ) - { - memcpy(from_tmp, from, from_pos); - sprintf(from_tmp+from_pos,"%02x/%s", i, from + from_pos); - /* Convert if not unix */ - unpack_filename(from_tmp, from_tmp); - if (my_delete(from_tmp, MyFlags)) - DBUG_RETURN(-1); - } - DBUG_RETURN(0); - } - - int my_raid_redel(const char *old_name, const char *new_name, - uint raid_chunks, myf MyFlags) - { - char new_name_buff[FN_REFLEN], old_name_buff[FN_REFLEN]; - char *new_end, *old_end; - uint i,old_length,new_length; - int error=0; - DBUG_ENTER("my_raid_redel"); - - old_end=old_name_buff+dirname_part(old_name_buff,old_name); - old_length=dirname_length(old_name); - new_end=new_name_buff+dirname_part(new_name_buff,new_name); - new_length=dirname_length(new_name); - for (i=0 ; i < raid_chunks ; i++) - { - MY_STAT status; - sprintf(new_end,"%02x",i); - if (my_stat(new_name_buff,&status, MYF(0))) - { - DBUG_PRINT("info",("%02x exists, skipping directory creation",i)); - } - else - { - if (my_mkdir(new_name_buff,0777,MYF(0))) - { - DBUG_PRINT("error",("mkdir failed for %02x",i)); - DBUG_RETURN(-1); - } - } - strxmov(strend(new_end),"/",new_name+new_length,NullS); - sprintf(old_end,"%02x/%s",i, old_name+old_length); - if (my_redel(old_name_buff, new_name_buff, MyFlags)) - error=1; - } - DBUG_RETURN(error); - } -} - -int my_raid_fstat(int fd, MY_STAT *stat_area, myf MyFlags ) -{ - DBUG_ENTER("my_raid_fstat"); - if (is_raid(fd)) - { - RaidFd *raid= (*dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); - DBUG_RETURN(raid->Fstat(fd, stat_area, MyFlags)); - } - else - DBUG_RETURN(my_fstat(fd, stat_area, MyFlags)); -} - - -/* -------------- RaidFd base class begins ----------------*/ -/* - RaidFd - raided file is identified by file descriptor - this is useful when we open/write/read/close files -*/ - - -bool RaidFd:: -IsRaid(File fd) -{ - DBUG_ENTER("RaidFd::IsRaid"); - DBUG_RETURN((uint) fd < _raid_map.elements && - *dynamic_element(&RaidFd::_raid_map,fd,RaidFd**)); -} - - -RaidFd:: -RaidFd(uint raid_type, uint raid_chunks, ulong raid_chunksize) - :_raid_type(raid_type), _raid_chunks(raid_chunks), - _raid_chunksize(raid_chunksize), _position(0), _size(RAID_SIZE_UNKNOWN), - _fd_vector(0) -{ - DBUG_ENTER("RaidFd::RaidFd"); - DBUG_PRINT("enter",("RaidFd_type: %u Disks: %u Chunksize: %d", - raid_type, raid_chunks, raid_chunksize)); - - /* TODO: Here we should add checks if the malloc fails */ - _seek_vector=0; /* In case of errors */ - my_multi_malloc(MYF(MY_WME), - &_seek_vector,sizeof(off_t)*_raid_chunks, - &_fd_vector, sizeof(File) *_raid_chunks, - NullS); - if (!RaidFd::_raid_map.buffer) - { /* Not initied */ - pthread_mutex_lock(&THR_LOCK_open); /* Ensure that no other thread */ - if (!RaidFd::_raid_map.buffer) /* has done init in between */ - init_raid(); - pthread_mutex_unlock(&THR_LOCK_open); - } - DBUG_VOID_RETURN; -} - - -RaidFd:: -~RaidFd() { - DBUG_ENTER("RaidFd::~RaidFd"); - /* We don't have to free _fd_vector ! */ - my_free((char*) _seek_vector, MYF(MY_ALLOW_ZERO_PTR)); - DBUG_VOID_RETURN; -} - - -File RaidFd:: -Create(const char *FileName, int CreateFlags, int access_flags, myf MyFlags) -{ - char RaidFdFileName[FN_REFLEN]; - DBUG_ENTER("RaidFd::Create"); - DBUG_PRINT("enter", - ("FileName: %s CreateFlags: %d access_flags: %d MyFlags: %d", - FileName, CreateFlags, access_flags, MyFlags)); - char DirName[FN_REFLEN]; - uint pos = dirname_part(DirName, FileName); - MY_STAT status; - if (!_seek_vector) - DBUG_RETURN(-1); /* Not enough memory */ - - uint i = _raid_chunks-1; - do - { - /* Create subdir */ - (void)sprintf(RaidFdFileName,"%s%02x", DirName,i); - unpack_dirname(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ - if (my_stat(RaidFdFileName,&status, MYF(0))) - { - DBUG_PRINT("info",("%02x exists, skipping directory creation",i)); - } - else - { - if (my_mkdir(RaidFdFileName,0777,MYF(0))) - { - DBUG_PRINT("error",("mkdir failed for %d",i)); - goto error; - } - } - /* Create file */ - sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); - unpack_filename(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ - _fd = my_create(RaidFdFileName, CreateFlags ,access_flags, (myf)MyFlags); - if (_fd < 0) - goto error; - _fd_vector[i]=_fd; - _seek_vector[i]=RAID_SEEK_DONE; - } while (i--); - _size=0; - DBUG_RETURN(_fd); /* Last filenr is pointer to map */ - -error: - { - int save_errno=my_errno; - while (++i < _raid_chunks) - { - my_close(_fd_vector[i],MYF(0)); - sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); - unpack_filename(RaidFdFileName,RaidFdFileName); - my_delete(RaidFdFileName,MYF(0)); - } - my_errno=save_errno; - } - DBUG_RETURN(-1); -} - - -File RaidFd:: -Open(const char *FileName, int Flags, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Open"); - DBUG_PRINT("enter",("FileName: %s Flags: %d MyFlags: %d", - FileName, Flags, MyFlags)); - char DirName[FN_REFLEN]; - uint pos = dirname_part(DirName, FileName); - if (!_seek_vector) - DBUG_RETURN(-1); /* Not enough memory */ - - for( uint i = 0 ; i < _raid_chunks ; i++ ) - { - char RaidFdFileName[FN_REFLEN]; - sprintf(RaidFdFileName,"%s%02x/%s",DirName, i, FileName + pos); - unpack_filename(RaidFdFileName,RaidFdFileName); /* Convert if not unix */ - _fd = my_open(RaidFdFileName, Flags, MyFlags); - if (_fd < 0) - { - int save_errno=my_errno; - while (i-- != 0) - my_close(_fd_vector[i],MYF(0)); - my_errno=save_errno; - DBUG_RETURN(_fd); - } - _fd_vector[i]=_fd; - _seek_vector[i]=RAID_SEEK_DONE; - } - Seek(0L,MY_SEEK_END,MYF(0)); // Trick. We just need to know, how big the file is - DBUG_PRINT("info",("MYD file logical size: %llu", _size)); - DBUG_RETURN(_fd); -} - - -int RaidFd:: -Write(const byte *Buffer, uint Count, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Write"); - DBUG_PRINT("enter",("Count: %d MyFlags: %d", - Count, MyFlags)); - const byte *bufptr = Buffer; - uint res=0, GotBytes, ReadNowCount; - - // Loop until data is written - do { - Calculate(); - // Do seeks when neccessary - if (_seek_vector[_this_block] != RAID_SEEK_DONE) - { - if (my_seek(_fd_vector[_this_block], _seek_vector[_this_block], - MY_SEEK_SET, - MyFlags) == MY_FILEPOS_ERROR) - DBUG_RETURN(-1); - _seek_vector[_this_block]=RAID_SEEK_DONE; - } - ReadNowCount = min(Count, _remaining_bytes); - GotBytes = my_write(_fd_vector[_this_block], bufptr, ReadNowCount, - MyFlags); - DBUG_PRINT("loop",("Wrote bytes: %d", GotBytes)); - if (GotBytes == MY_FILE_ERROR) - DBUG_RETURN(-1); - res+= GotBytes; - if (MyFlags & (MY_NABP | MY_FNABP)) - GotBytes=ReadNowCount; - bufptr += GotBytes; - Count -= GotBytes; - _position += GotBytes; - } while(Count); - set_if_bigger(_size,_position); - DBUG_RETURN(res); -} - - -int RaidFd:: -Read(const byte *Buffer, uint Count, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Read"); - DBUG_PRINT("enter",("Count: %d MyFlags: %d", - Count, MyFlags)); - byte *bufptr = (byte *)Buffer; - uint res= 0, GotBytes, ReadNowCount; - - // Loop until all data is read (Note that Count may be 0) - while (Count) - { - Calculate(); - // Do seek when neccessary - if (_seek_vector[_this_block] != RAID_SEEK_DONE) - { - if (my_seek(_fd_vector[_this_block], _seek_vector[_this_block], - MY_SEEK_SET, - MyFlags) == MY_FILEPOS_ERROR) - DBUG_RETURN(-1); - _seek_vector[_this_block]=RAID_SEEK_DONE; - } - // and read - ReadNowCount = min(Count, _remaining_bytes); - GotBytes = my_read(_fd_vector[_this_block], bufptr, ReadNowCount, - MyFlags & ~(MY_NABP | MY_FNABP)); - DBUG_PRINT("loop",("Got bytes: %u", GotBytes)); - if (GotBytes == MY_FILE_ERROR) - DBUG_RETURN(-1); - if (!GotBytes) // End of file. - { - DBUG_RETURN((MyFlags & (MY_NABP | MY_FNABP)) ? -1 : (int) res); - } - res+= GotBytes; - bufptr += GotBytes; - Count -= GotBytes; - _position += GotBytes; - } - DBUG_RETURN((MyFlags & (MY_NABP | MY_FNABP)) ? 0 : res); -} - - -int RaidFd:: -Lock(int locktype, my_off_t start, my_off_t length, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Lock"); - DBUG_PRINT("enter",("locktype: %d start: %lu length: %lu MyFlags: %d", - locktype, start, length, MyFlags)); - my_off_t bufptr = start; - // Loop until all data is locked - while(length) - { - Calculate(); - for (uint i = _this_block ; (i < _raid_chunks) && length ; i++ ) - { - uint ReadNowCount = min(length, _remaining_bytes); - uint GotBytes = my_lock(_fd_vector[i], locktype, bufptr, ReadNowCount, - MyFlags); - if ((int) GotBytes == -1) - DBUG_RETURN(-1); - bufptr += ReadNowCount; - length -= ReadNowCount; - Calculate(); - } - } - DBUG_RETURN(0); -} - - -int RaidFd:: -Close(myf MyFlags) -{ - DBUG_ENTER("RaidFd::Close"); - DBUG_PRINT("enter",("MyFlags: %d", - MyFlags)); - for (uint i = 0 ; i < _raid_chunks ; ++i ) - { - int err = my_close(_fd_vector[i], MyFlags); - if (err != 0) - DBUG_RETURN(err); - } - /* _fd_vector is erased when RaidFd is released */ - DBUG_RETURN(0); -} - - -my_off_t RaidFd:: -Seek(my_off_t pos,int whence,myf MyFlags) -{ - DBUG_ENTER("RaidFd::Seek"); - DBUG_PRINT("enter",("Pos: %lu Whence: %d MyFlags: %d", - (ulong) pos, whence, MyFlags)); - switch (whence) { - case MY_SEEK_CUR: - // FIXME: This is wrong, what is going on there - // Just I am relied on fact that MySQL 3.23.7 never uses MY_SEEK_CUR - // for anything else except things like ltell() - break; - case MY_SEEK_SET: - if ( _position != pos) // we can be already in right place - { - uint i; - off_t _rounds; - _position = pos; - Calculate(); - _rounds = _total_block / _raid_chunks; // INT() assumed - _rounds*= _raid_chunksize; - for (i = 0; i < _raid_chunks ; i++ ) - if ( i < _this_block ) - _seek_vector[i] = _rounds + _raid_chunksize; - else if ( i == _this_block ) - _seek_vector[i] = _rounds + _raid_chunksize -_remaining_bytes; - else // if ( i > _this_block ) - _seek_vector[i] = _rounds; - } - break; - case MY_SEEK_END: - if (_size==RAID_SIZE_UNKNOWN) // We don't know table size yet - { - uint i; - _position = 0; - for (i = 0; i < _raid_chunks ; i++ ) - { - my_off_t newpos = my_seek(_fd_vector[i], 0L, MY_SEEK_END, MyFlags); - if (newpos == MY_FILEPOS_ERROR) - DBUG_RETURN (MY_FILEPOS_ERROR); - _seek_vector[i]=RAID_SEEK_DONE; - _position += newpos; - } - _size=_position; - } - else if (_position != _size) // Aren't we also already in the end? - { - uint i; - off_t _rounds; - _position = _size; - Calculate(); - _rounds = _total_block / _raid_chunks; // INT() assumed - _rounds*= _raid_chunksize; - for (i = 0; i < _raid_chunks ; i++ ) - if ( i < _this_block ) - _seek_vector[i] = _rounds + _raid_chunksize; - else if ( i == _this_block ) - _seek_vector[i] = _rounds + _raid_chunksize - _remaining_bytes; - else // if ( i > _this_block ) - _seek_vector[i] = _rounds; - _position=_size; - } - } - DBUG_RETURN(_position); -} - - -my_off_t RaidFd:: -Tell(myf MyFlags) -{ - DBUG_ENTER("RaidFd::Tell"); - DBUG_PRINT("enter",("MyFlags: %d _position %d", - MyFlags,_position)); - DBUG_RETURN(_position); -} - -int RaidFd:: -Chsize(File fd, my_off_t newlength, int filler, myf MyFlags) -{ - DBUG_ENTER("RaidFd::Chsize"); - DBUG_PRINT("enter",("Fd: %d, newlength: %d, MyFlags: %d", - fd, newlength,MyFlags)); - _position = newlength; - Calculate(); - uint _rounds = _total_block / _raid_chunks; // INT() assumed - for (uint i = 0; i < _raid_chunks ; i++ ) - { - int newpos; - if ( i < _this_block ) - newpos = my_chsize(_fd_vector[i], - _this_block * _raid_chunksize + (_rounds + 1) * - _raid_chunksize, filler, MyFlags); - else if ( i == _this_block ) - newpos = my_chsize(_fd_vector[i], - _this_block * _raid_chunksize + _rounds * - _raid_chunksize + (newlength % _raid_chunksize), - filler, MyFlags); - else // this means: i > _this_block - newpos = my_chsize(_fd_vector[i], - _this_block * _raid_chunksize + _rounds * - _raid_chunksize, filler, MyFlags); - if (newpos) - DBUG_RETURN(1); - } - DBUG_RETURN(0); -} - - -int RaidFd:: -Fstat(int fd, MY_STAT *stat_area, myf MyFlags ) -{ - DBUG_ENTER("RaidFd::Fstat"); - DBUG_PRINT("enter",("fd: %d MyFlags: %d",fd,MyFlags)); - uint i; - int error=0; - MY_STAT status; - stat_area->st_size=0; - stat_area->st_mtime=0; - stat_area->st_atime=0; - stat_area->st_ctime=0; - - for(i=0 ; i < _raid_chunks ; i++) - { - if (my_fstat(_fd_vector[i],&status,MyFlags)) - error=1; - stat_area->st_size+=status.st_size; - set_if_bigger(stat_area->st_mtime,status.st_mtime); - set_if_bigger(stat_area->st_atime,status.st_atime); - set_if_bigger(stat_area->st_ctime,status.st_ctime); - } - DBUG_RETURN(error); -} - -#endif /* defined(USE_RAID) && !defined(MYSQL_CLIENT) */ diff --git a/mysys/raid2.c b/mysys/raid2.c deleted file mode 100644 index 4feace7410f..00000000000 --- a/mysys/raid2.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Copyright (C) 2002 MySQL AB - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; version 2 - of the License. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA */ - -/* - RAID support for MySQL. For full comments, check raid.cc - This is in a separate file to not cause problems on OS that can't - put C++ files in archives. -*/ - -#include "mysys_priv.h" - -const char *raid_type_string[]={"none","striped"}; - -const char *my_raid_type(int raid_type) -{ - return raid_type_string[raid_type]; -} diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index f43c860adb0..da15b02345b 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -524,7 +524,7 @@ char *_my_strdup(const char *from, const char *filename, uint lineno, } /* _my_strdup */ -char *_my_strdup_with_length(const char *from, uint length, +char *_my_strndup(const char *from, uint length, const char *filename, uint lineno, myf MyFlags) { diff --git a/mysys/string.c b/mysys/string.c index e64156d430e..86de7bfcf69 100644 --- a/mysys/string.c +++ b/mysys/string.c @@ -114,6 +114,12 @@ my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, return FALSE; } +my_bool dynstr_trunc(DYNAMIC_STRING *str, int n) +{ + str->length-=n; + str->str[str->length]= '\0'; + return FALSE; +} void dynstr_free(DYNAMIC_STRING *str) { diff --git a/mysys/test_dir.c b/mysys/test_dir.c index f1e4987371b..54e6c99e21e 100644 --- a/mysys/test_dir.c +++ b/mysys/test_dir.c @@ -15,7 +15,6 @@ /* TODO: Test all functions */ -#define USES_TYPES #include "mysys_priv.h" #include "my_dir.h" diff --git a/mysys/testhash.c b/mysys/testhash.c index fd2bc73b2ae..0961558afd3 100644 --- a/mysys/testhash.c +++ b/mysys/testhash.c @@ -249,7 +249,6 @@ err: static int get_options(int argc, char **argv) { char *pos,*progname; - DEBUGGER_OFF; progname= argv[0]; @@ -269,7 +268,6 @@ static int get_options(int argc, char **argv) printf("Usage: %s [-?ABIKLWv] [-m#] [-t#]\n",progname); exit(0); case '#': - DEBUGGER_ON; DBUG_PUSH (++pos); break; } diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index acb4ac5dbf9..170ee8a1b73 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -14,8 +14,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* To avoid problems with alarms in debug code, we disable DBUG here */ -#undef DBUG_OFF -#define DBUG_OFF +#define FORCE_DBUG_OFF #include <my_global.h> #if defined(THREAD) && !defined(DONT_USE_THR_ALARM) @@ -41,7 +40,7 @@ volatile my_bool alarm_thread_running= 0; static sig_handler process_alarm_part2(int sig); -#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) +#if !defined(__WIN__) static pthread_mutex_t LOCK_alarm; static pthread_cond_t COND_alarm; @@ -276,7 +275,7 @@ sig_handler process_alarm(int sig __attribute__((unused))) if (!pthread_equal(pthread_self(),alarm_thread)) { #if defined(MAIN) && !defined(__bsdi__) - printf("thread_alarm\n"); fflush(stdout); + printf("thread_alarm in process_alarm\n"); fflush(stdout); #endif #ifdef DONT_REMEMBER_SIGNAL my_sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */ @@ -563,145 +562,6 @@ static void *alarm_handler(void *arg __attribute__((unused))) #endif /* USE_ALARM_THREAD */ /***************************************************************************** - thr_alarm for OS/2 -*****************************************************************************/ - -#elif defined(__EMX__) || defined(OS2) - -#define INCL_BASE -#define INCL_NOPMAPI -#include <os2.h> - -static pthread_mutex_t LOCK_alarm; -static sigset_t full_signal_set; -static QUEUE alarm_queue; -pthread_t alarm_thread; - -#ifdef USE_ALARM_THREAD -static pthread_cond_t COND_alarm; -static void *alarm_handler(void *arg); -#define reschedule_alarms() pthread_cond_signal(&COND_alarm) -#else -#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) -#endif - -sig_handler process_alarm(int sig __attribute__((unused))) -{ - sigset_t old_mask; - ALARM *alarm_data; - DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements)); -} - - -/* - Remove another thread from the alarm -*/ - -void thr_alarm_kill(pthread_t thread_id) -{ - uint i; - - pthread_mutex_lock(&LOCK_alarm); - for (i=0 ; i < alarm_queue.elements ; i++) - { - if (pthread_equal(((ALARM*) queue_element(&alarm_queue,i))->thread, - thread_id)) - { - ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i); - tmp->expire_time=0; - queue_insert(&alarm_queue,(byte*) tmp); - reschedule_alarms(); - break; - } - } - pthread_mutex_unlock(&LOCK_alarm); -} - -bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm) -{ - APIRET rc; - if (alarm_aborted) - { - alarm->alarmed.crono=0; - alarm->alarmed.event=0; - return 1; - } - if (rc = DosCreateEventSem(NULL,(HEV *) &alarm->alarmed.event, - DC_SEM_SHARED,FALSE)) - { - printf("Error creating event semaphore! [%d] \n",rc); - alarm->alarmed.crono=0; - alarm->alarmed.event=0; - return 1; - } - if (rc = DosAsyncTimer((long) sec*1000L, (HSEM) alarm->alarmed.event, - (HTIMER *) &alarm->alarmed.crono)) - { - printf("Error starting async timer! [%d] \n",rc); - DosCloseEventSem((HEV) alarm->alarmed.event); - alarm->alarmed.crono=0; - alarm->alarmed.event=0; - return 1; - } /* endif */ - (*alrm)= &alarm->alarmed; - return 1; -} - - -bool thr_got_alarm(thr_alarm_t *alrm_ptr) -{ - thr_alarm_t alrm= *alrm_ptr; - APIRET rc; - - if (alrm->crono) - { - rc = DosWaitEventSem((HEV) alrm->event, SEM_IMMEDIATE_RETURN); - if (rc == 0) { - DosCloseEventSem((HEV) alrm->event); - alrm->crono = 0; - alrm->event = 0; - } /* endif */ - } - return !alrm->crono || alarm_aborted; -} - - -void thr_end_alarm(thr_alarm_t *alrm_ptr) -{ - thr_alarm_t alrm= *alrm_ptr; - if (alrm->crono) - { - DosStopTimer((HTIMER) alrm->crono); - DosCloseEventSem((HEV) alrm->event); - alrm->crono = 0; - alrm->event = 0; - } -} - -void end_thr_alarm(my_bool free_structures) -{ - DBUG_ENTER("end_thr_alarm"); - alarm_aborted=1; /* No more alarms */ - DBUG_VOID_RETURN; -} - -void init_thr_alarm(uint max_alarm) -{ - DBUG_ENTER("init_thr_alarm"); - alarm_aborted=0; /* Yes, Gimmie alarms */ - DBUG_VOID_RETURN; -} - -void thr_alarm_info(ALARM_INFO *info) -{ - bzero((char*) info, sizeof(*info)); -} - -void resize_thr_alarm(uint max_alarms) -{ -} - -/***************************************************************************** thr_alarm for win95 *****************************************************************************/ @@ -901,10 +761,8 @@ static sig_handler print_signal_warning(int sig) #ifdef DONT_REMEMBER_SIGNAL my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif -#ifndef OS2 if (sig == SIGALRM) alarm(2); /* reschedule alarm */ -#endif } #endif /* USE_ONE_SIGNAL_HAND */ @@ -921,7 +779,6 @@ static void *signal_hand(void *arg __attribute__((unused))) VOID(pthread_cond_signal(&COND_thread_count)); /* Tell main we are ready */ pthread_mutex_unlock(&LOCK_thread_count); -#ifndef OS2 sigemptyset(&set); /* Catch all signals */ sigaddset(&set,SIGINT); sigaddset(&set,SIGQUIT); @@ -938,7 +795,6 @@ static void *signal_hand(void *arg __attribute__((unused))) #else puts("Starting signal handling thread"); #endif -#endif /* OS2 */ printf("server alarm: %d thread alarm: %d\n", THR_SERVER_ALARM,THR_CLIENT_ALARM); DBUG_PRINT("info",("Starting signal and alarm handling thread")); @@ -961,9 +817,7 @@ static void *signal_hand(void *arg __attribute__((unused))) case SIGINT: case SIGQUIT: case SIGTERM: -#ifndef OS2 case SIGHUP: -#endif printf("Aborting nicely\n"); end_thr_alarm(0); break; @@ -973,13 +827,11 @@ static void *signal_hand(void *arg __attribute__((unused))) exit(1); return 0; /* Keep some compilers happy */ #endif -#ifndef OS2 #ifdef USE_ONE_SIGNAL_HAND case THR_SERVER_ALARM: process_alarm(sig); break; #endif -#endif /* OS2 */ } } } @@ -995,13 +847,13 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) MY_INIT(argv[0]); if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') + { DBUG_PUSH(argv[1]+2); - + } pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST); pthread_cond_init(&COND_thread_count,NULL); /* Start a alarm handling thread */ -#ifndef OS2 sigemptyset(&set); sigaddset(&set,SIGINT); sigaddset(&set,SIGQUIT); @@ -1019,7 +871,6 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) sigaddset(&set,THR_CLIENT_ALARM); VOID(pthread_sigmask(SIG_UNBLOCK, &set, (sigset_t*) 0)); #endif -#endif /* OS2 */ pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); @@ -1066,8 +917,8 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) } } pthread_mutex_unlock(&LOCK_thread_count); - end_thr_alarm(1); thr_alarm_info(&alarm_info); + end_thr_alarm(1); printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n", alarm_info.active_alarms, alarm_info.max_used_alarms, alarm_info.next_alarm_time); diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 27203c2d23c..2a1b94a363e 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -71,7 +71,7 @@ multiple read locks. */ #if !defined(MAIN) && !defined(DBUG_OFF) && !defined(EXTRA_DEBUG) -#define DBUG_OFF +#define FORCE_DBUG_OFF #endif #include "mysys_priv.h" @@ -481,7 +481,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, data->type=lock_type; data->owner= owner; /* Must be reset ! */ VOID(pthread_mutex_lock(&lock->mutex)); - DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx type: %d", + DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx type: %d", (long) data, data->owner->info->thread_id, (long) lock, (int) lock_type)); check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? @@ -500,7 +500,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, and the read lock is not TL_READ_NO_INSERT */ - DBUG_PRINT("lock",("write locked by thread: %ld", + DBUG_PRINT("lock",("write locked by thread: 0x%lx", lock->write.data->owner->info->thread_id)); if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || (lock->write.data->type <= TL_WRITE_DELAYED && @@ -622,7 +622,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, statistic_increment(locks_immediate,&THR_LOCK_lock); goto end; } - DBUG_PRINT("lock",("write locked by thread: %ld", + DBUG_PRINT("lock",("write locked by thread: 0x%lx", lock->write.data->owner->info->thread_id)); } else @@ -658,7 +658,7 @@ thr_lock(THR_LOCK_DATA *data, THR_LOCK_OWNER *owner, goto end; } } - DBUG_PRINT("lock",("write locked by thread: %ld, type: %d", + DBUG_PRINT("lock",("write locked by thread: 0x%lx, type: %d", lock->read.data->owner->info->thread_id, data->type)); } wait_queue= &lock->write_wait; @@ -720,7 +720,7 @@ static inline void free_all_read_locks(THR_LOCK *lock, } lock->read_no_write_count++; } - DBUG_PRINT("lock",("giving read lock to thread: %ld", + DBUG_PRINT("lock",("giving read lock to thread: 0x%lx", data->owner->info->thread_id)); data->cond=0; /* Mark thread free */ VOID(pthread_cond_signal(cond)); @@ -738,7 +738,7 @@ void thr_unlock(THR_LOCK_DATA *data) THR_LOCK *lock=data->lock; enum thr_lock_type lock_type=data->type; DBUG_ENTER("thr_unlock"); - DBUG_PRINT("lock",("data: 0x%lx thread: %ld lock: 0x%lx", + DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx", (long) data, data->owner->info->thread_id, (long) lock)); pthread_mutex_lock(&lock->mutex); check_locks(lock,"start of release lock",0); @@ -798,7 +798,7 @@ void thr_unlock(THR_LOCK_DATA *data) if (data->type == TL_WRITE_CONCURRENT_INSERT && (*lock->check_status)(data->status_param)) data->type=TL_WRITE; /* Upgrade lock */ - DBUG_PRINT("lock",("giving write lock of type %d to thread: %ld", + DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx", data->type, data->owner->info->thread_id)); { pthread_cond_t *cond=data->cond; @@ -1011,7 +1011,7 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count) TL_WRITE_ONLY to abort any new accesses to the lock */ -void thr_abort_locks(THR_LOCK *lock) +void thr_abort_locks(THR_LOCK *lock, bool upgrade_lock) { THR_LOCK_DATA *data; DBUG_ENTER("thr_abort_locks"); @@ -1033,7 +1033,7 @@ void thr_abort_locks(THR_LOCK *lock) lock->read_wait.last= &lock->read_wait.data; lock->write_wait.last= &lock->write_wait.data; lock->read_wait.data=lock->write_wait.data=0; - if (lock->write.data) + if (upgrade_lock && lock->write.data) lock->write.data->type=TL_WRITE_ONLY; pthread_mutex_unlock(&lock->mutex); DBUG_VOID_RETURN; @@ -1091,6 +1091,216 @@ my_bool thr_abort_locks_for_thread(THR_LOCK *lock, pthread_t thread) } +/* + Downgrade a WRITE_* to a lower WRITE level + SYNOPSIS + thr_downgrade_write_lock() + in_data Lock data of thread downgrading its lock + new_lock_type New write lock type + RETURN VALUE + NONE + DESCRIPTION + This can be used to downgrade a lock already owned. When the downgrade + occurs also other waiters, both readers and writers can be allowed to + start. + The previous lock is often TL_WRITE_ONLY but can also be + TL_WRITE and TL_WRITE_ALLOW_READ. The normal downgrade variants are + TL_WRITE_ONLY => TL_WRITE_ALLOW_READ After a short exclusive lock + TL_WRITE_ALLOW_READ => TL_WRITE_ALLOW_WRITE After discovering that the + operation didn't need such a high lock. + TL_WRITE_ONLY => TL_WRITE after a short exclusive lock while holding a + write table lock + TL_WRITE_ONLY => TL_WRITE_ALLOW_WRITE After a short exclusive lock after + already earlier having dongraded lock to TL_WRITE_ALLOW_WRITE + The implementation is conservative and rather don't start rather than + go on unknown paths to start, the common cases are handled. + + NOTE: + In its current implementation it is only allowed to downgrade from + TL_WRITE_ONLY. In this case there are no waiters. Thus no wake up + logic is required. +*/ + +void thr_downgrade_write_lock(THR_LOCK_DATA *in_data, + enum thr_lock_type new_lock_type) +{ + THR_LOCK *lock=in_data->lock; + enum thr_lock_type old_lock_type= in_data->type; +#ifdef TO_BE_REMOVED + THR_LOCK_DATA *data, *next; + bool start_writers= FALSE; + bool start_readers= FALSE; +#endif + DBUG_ENTER("thr_downgrade_write_only_lock"); + + pthread_mutex_lock(&lock->mutex); + DBUG_ASSERT(old_lock_type == TL_WRITE_ONLY); + DBUG_ASSERT(old_lock_type > new_lock_type); + in_data->type= new_lock_type; + check_locks(lock,"after downgrading lock",0); + +#if TO_BE_REMOVED + switch (old_lock_type) + { + case TL_WRITE_ONLY: + case TL_WRITE: + case TL_WRITE_LOW_PRIORITY: + /* + Previous lock was exclusive we are now ready to start up most waiting + threads. + */ + switch (new_lock_type) + { + case TL_WRITE_ALLOW_READ: + /* Still cannot start WRITE operations. Can only start readers. */ + start_readers= TRUE; + break; + case TL_WRITE: + case TL_WRITE_LOW_PRIORITY: + /* + Still cannot start anything, but new requests are no longer + aborted. + */ + break; + case TL_WRITE_ALLOW_WRITE: + /* + We can start both writers and readers. + */ + start_writers= TRUE; + start_readers= TRUE; + break; + case TL_WRITE_CONCURRENT_INSERT: + case TL_WRITE_DELAYED: + /* + This routine is not designed for those. Lock will be downgraded + but no start of waiters will occur. This is not the optimal but + should be a correct behaviour. + */ + break; + default: + DBUG_ASSERT(0); + } + break; + case TL_WRITE_DELAYED: + case TL_WRITE_CONCURRENT_INSERT: + /* + This routine is not designed for those. Lock will be downgraded + but no start of waiters will occur. This is not the optimal but + should be a correct behaviour. + */ + break; + case TL_WRITE_ALLOW_READ: + DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE); + /* + Previously writers were not allowed to start, now it is ok to + start them again. Readers are already allowed so no reason to + handle them. + */ + start_writers= TRUE; + break; + default: + DBUG_ASSERT(0); + break; + } + if (start_writers) + { + /* + At this time the only active writer can be ourselves. Thus we need + not worry about that there are other concurrent write operations + active on the table. Thus we only need to worry about starting + waiting operations. + We also only come here with TL_WRITE_ALLOW_WRITE as the new + lock type, thus we can start other writers also of the same type. + If we find a lock at exclusive level >= TL_WRITE_LOW_PRIORITY we + don't start any more operations that would be mean those operations + will have to wait for things started afterwards. + */ + DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE); + for (data=lock->write_wait.data; data ; data= next) + { + /* + All WRITE requests compatible with new lock type are also + started + */ + next= data->next; + if (start_writers && data->type == new_lock_type) + { + pthread_cond_t *cond= data->cond; + /* + It is ok to start this waiter. + Move from being first in wait queue to be last in write queue. + */ + if (((*data->prev)= data->next)) + data->next->prev= data->prev; + else + lock->write_wait.last= data->prev; + data->prev= lock->write.last; + lock->write.last= &data->next; + data->next= 0; + check_locks(lock, "Started write lock after downgrade",0); + data->cond= 0; + pthread_cond_signal(cond); + } + else + { + /* + We found an incompatible lock, we won't start any more write + requests to avoid letting writers pass other writers in the + queue. + */ + start_writers= FALSE; + if (data->type >= TL_WRITE_LOW_PRIORITY) + { + /* + We have an exclusive writer in the queue so we won't start + readers either. + */ + start_readers= FALSE; + } + } + } + } + if (start_readers) + { + DBUG_ASSERT(new_lock_type == TL_WRITE_ALLOW_WRITE || + new_lock_type == TL_WRITE_ALLOW_READ); + /* + When we come here we know that the write locks are + TL_WRITE_ALLOW_WRITE or TL_WRITE_ALLOW_READ. This means that reads + are ok + */ + for (data=lock->read_wait.data; data ; data=next) + { + next= data->next; + /* + All reads are ok to start now except TL_READ_NO_INSERT when + write lock is TL_WRITE_ALLOW_READ. + */ + if (new_lock_type != TL_WRITE_ALLOW_READ || + data->type != TL_READ_NO_INSERT) + { + pthread_cond_t *cond= data->cond; + if (((*data->prev)= data->next)) + data->next->prev= data->prev; + else + lock->read_wait.last= data->prev; + data->prev= lock->read.last; + lock->read.last= &data->next; + data->next= 0; + + if (data->type == TL_READ_NO_INSERT) + lock->read_no_write_count++; + check_locks(lock, "Started read lock after downgrade",0); + data->cond= 0; + pthread_cond_signal(cond); + } + } + } + check_locks(lock,"after starting waiters after downgrading lock",0); +#endif + pthread_mutex_unlock(&lock->mutex); + DBUG_VOID_RETURN; +} /* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */ diff --git a/mysys/thr_mutex.c b/mysys/thr_mutex.c index 425e5fce459..42f9fe5f600 100644 --- a/mysys/thr_mutex.c +++ b/mysys/thr_mutex.c @@ -356,3 +356,80 @@ void safe_mutex_end(FILE *file __attribute__((unused))) } #endif /* THREAD && SAFE_MUTEX */ + +#if defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) + +#include "mysys_priv.h" +#include "my_static.h" +#include <m_string.h> + +#include <m_ctype.h> +#include <hash.h> +#include <myisampack.h> +#include <mysys_err.h> +#include <my_sys.h> + +#undef pthread_mutex_t +#undef pthread_mutex_init +#undef pthread_mutex_lock +#undef pthread_mutex_trylock +#undef pthread_mutex_unlock +#undef pthread_mutex_destroy +#undef pthread_cond_wait +#undef pthread_cond_timedwait + +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 + +int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, + const pthread_mutexattr_t *attr) +{ + static int cpu_count= 0; +#ifdef _SC_NPROCESSORS_CONF + if (!cpu_count && (attr == MY_MUTEX_INIT_FAST)) + cpu_count= sysconf(_SC_NPROCESSORS_CONF); +#endif + + if ((cpu_count > 1) && (attr == MY_MUTEX_INIT_FAST)) + mp->spins= MY_PTHREAD_FASTMUTEX_SPINS; + else + mp->spins= 0; + return pthread_mutex_init(&mp->mutex, attr); +} + +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 += ((double) random() / (double) RAND_MAX) * + MY_PTHREAD_FASTMUTEX_DELAY + 1; + } + return pthread_mutex_lock(&mp->mutex); +} +#endif /* defined(THREAD) && defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) */ diff --git a/mysys/trie.c b/mysys/trie.c new file mode 100644 index 00000000000..8daa6f3e661 --- /dev/null +++ b/mysys/trie.c @@ -0,0 +1,236 @@ +/* Copyright (C) 2005 MySQL AB + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Implementation of trie and Aho-Corasick automaton. + Supports only charsets that can be compared byte-wise. + + TODO: + Add character frequencies. Can increase lookup speed + up to 30%. + Implement character-wise comparision. +*/ + + +#include "mysys_priv.h" +#include <m_string.h> +#include <my_trie.h> +#include <my_base.h> + + +/* + SYNOPSIS + TRIE *trie_init (TRIE *trie, CHARSET_INFO *charset); + + DESCRIPTION + Allocates or initializes a `TRIE' object. If `trie' is a `NULL' + pointer, the function allocates, initializes, and returns a new + object. Otherwise, the object is initialized and the address of + the object is returned. If `trie_init()' allocates a new object, + it will be freed when `trie_free()' is called. + + RETURN VALUE + An initialized `TRIE*' object. `NULL' if there was insufficient + memory to allocate a new object. +*/ + +TRIE *trie_init (TRIE *trie, CHARSET_INFO *charset) +{ + MEM_ROOT mem_root; + DBUG_ENTER("trie_init"); + DBUG_ASSERT(charset); + init_alloc_root(&mem_root, + (sizeof(TRIE_NODE) * 128) + ALLOC_ROOT_MIN_BLOCK_SIZE, + sizeof(TRIE_NODE) * 128); + if (! trie) + { + if (! (trie= (TRIE *)alloc_root(&mem_root, sizeof(TRIE)))) + { + free_root(&mem_root, MYF(0)); + DBUG_RETURN(NULL); + } + } + + memcpy(&trie->mem_root, &mem_root, sizeof(MEM_ROOT)); + trie->root.leaf= 0; + trie->root.c= 0; + trie->root.next= NULL; + trie->root.links= NULL; + trie->root.fail= NULL; + trie->charset= charset; + trie->nnodes= 0; + trie->nwords= 0; + DBUG_RETURN(trie); +} + + +/* + SYNOPSIS + void trie_free (TRIE *trie); + trie - valid pointer to `TRIE' + + DESCRIPTION + Frees the memory allocated for a `trie'. + + RETURN VALUE + None. +*/ + +void trie_free (TRIE *trie) +{ + MEM_ROOT mem_root; + DBUG_ENTER("trie_free"); + DBUG_ASSERT(trie); + memcpy(&mem_root, &trie->mem_root, sizeof(MEM_ROOT)); + free_root(&mem_root, MYF(0)); + DBUG_VOID_RETURN; +} + + +/* + SYNOPSIS + my_bool trie_insert (TRIE *trie, const byte *key, uint keylen); + trie - valid pointer to `TRIE' + key - valid pointer to key to insert + keylen - non-0 key length + + DESCRIPTION + Inserts new key into trie. + + RETURN VALUE + Upon successful completion, `trie_insert' returns `FALSE'. Otherwise + `TRUE' is returned. + + NOTES + If this function fails you must assume `trie' is broken. + However it can be freed with trie_free(). +*/ + +my_bool trie_insert (TRIE *trie, const byte *key, uint keylen) +{ + TRIE_NODE *node; + TRIE_NODE *next; + byte p; + uint k; + DBUG_ENTER("trie_insert"); + DBUG_ASSERT(trie && key && keylen); + node= &trie->root; + trie->root.fail= NULL; + for (k= 0; k < keylen; k++) + { + p= key[k]; + for (next= node->links; next; next= next->next) + if (next->c == p) + break; + + if (! next) + { + TRIE_NODE *tmp= (TRIE_NODE *)alloc_root(&trie->mem_root, + sizeof(TRIE_NODE)); + if (! tmp) + DBUG_RETURN(TRUE); + tmp->leaf= 0; + tmp->c= p; + tmp->links= tmp->fail= tmp->next= NULL; + trie->nnodes++; + if (! node->links) + { + node->links= tmp; + } + else + { + for (next= node->links; next->next; next= next->next) /* no-op */; + next->next= tmp; + } + node= tmp; + } + else + { + node= next; + } + } + node->leaf= keylen; + trie->nwords++; + DBUG_RETURN(FALSE); +} + + +/* + SYNOPSIS + my_bool trie_prepare (TRIE *trie); + trie - valid pointer to `TRIE' + + DESCRIPTION + Constructs Aho-Corasick automaton. + + RETURN VALUE + Upon successful completion, `trie_prepare' returns `FALSE'. Otherwise + `TRUE' is returned. +*/ + +my_bool ac_trie_prepare (TRIE *trie) +{ + TRIE_NODE **tmp_nodes; + TRIE_NODE *node; + uint32 fnode= 0; + uint32 lnode= 0; + DBUG_ENTER("trie_prepare"); + DBUG_ASSERT(trie); + + tmp_nodes= (TRIE_NODE **)my_malloc(trie->nnodes * sizeof(TRIE_NODE *), MYF(0)); + if (! tmp_nodes) + DBUG_RETURN(TRUE); + + trie->root.fail= &trie->root; + for (node= trie->root.links; node; node= node->next) + { + node->fail= &trie->root; + tmp_nodes[lnode++]= node; + } + + while (fnode < lnode) + { + TRIE_NODE *current= (TRIE_NODE *)tmp_nodes[fnode++]; + for (node= current->links; node; node= node->next) + { + TRIE_NODE *fail= current->fail; + tmp_nodes[lnode++]= node; + while (! (node->fail= trie_goto(&trie->root, fail, node->c))) + fail= fail->fail; + } + } + my_free((gptr)tmp_nodes, MYF(0)); + DBUG_RETURN(FALSE); +} + + +/* + SYNOPSIS + void ac_trie_init (TRIE *trie, AC_TRIE_STATE *state); + trie - valid pointer to `TRIE' + state - value pointer to `AC_TRIE_STATE' + + DESCRIPTION + Initializes `AC_TRIE_STATE' object. +*/ + +void ac_trie_init (TRIE *trie, AC_TRIE_STATE *state) +{ + DBUG_ENTER("ac_trie_init"); + DBUG_ASSERT(trie && state); + state->trie= trie; + state->node= &trie->root; + DBUG_VOID_RETURN; +} |