diff options
| author | Vincent-Michael <Vincent_Michael@gmx.de> | 2014-08-26 19:21:22 +0200 |
|---|---|---|
| committer | Vincent-Michael <Vincent_Michael@gmx.de> | 2014-08-26 19:21:22 +0200 |
| commit | 741f3dde2e880baf3439fe60f7166cea14b70196 (patch) | |
| tree | c7f49c46c258d1a587dee4b4367f5436a833c93e /dep/mysqllite/mysys | |
| parent | 67fc6a9b42879bc6ea9010293780d4f82d9cb09e (diff) | |
| parent | febb26d4b711762b1ee605705e7fa949b9871df1 (diff) | |
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts:
dep/PackageList.txt
src/server/game/Spells/Auras/SpellAuras.cpp
Diffstat (limited to 'dep/mysqllite/mysys')
114 files changed, 0 insertions, 38288 deletions
diff --git a/dep/mysqllite/mysys/ChangeLog b/dep/mysqllite/mysys/ChangeLog deleted file mode 100644 index 7a426106667..00000000000 --- a/dep/mysqllite/mysys/ChangeLog +++ /dev/null @@ -1,221 +0,0 @@ -2000-02-16 Michael Widenius <monty@monty.pp.sci.fi> - -* Added an extra argument to the compare routine for queues to allow - more advanced key compare functions. - -2000-02-10 Michael Widenius <monty@monty.pp.sci.fi> - -* Added THR_READ_NO_INSERT lock privilege to thr_lock. - -1999-08-21 Michael Widenius <monty@tik.pp.sci.fi> - -* Fix that '-1.49 or -1.49' is true -* Allow negative hexadecimal numbers (like -0x0f). -* Fixed problem with auto_increment on float and double. - -Wed Dec 17 02:13:58 1997 <monty@monty.pp.sci.fi> - -* Faster flush of keycache. - -Sat Dec 2 21:36:20 1995 Michael Widenius (monty@bitch) - - * array.c push_element & alloc_element. - -Wed Mar 3 00:54:20 1993 Michael Widenius (monty@bitch) - - * Removed automatic O_TRUNC from my_create. - -Wed Oct 28 02:10:56 1992 Michael Widenius (monty@bitch) - - * Enabled ASNYNC_IO on SUN. - -Mon Aug 31 23:51:13 1992 Michael Widenius (monty@bitch) - - * Changed tree_insert to return element if ok. - * Added new define tree_set_pointer(). - * Chagned delete_queue() to not free if allready freed. - -Mon Aug 17 01:46:36 1992 Michael Widenius (monty@bitch) - - * Added ny cashing-rutine mf_iocash for quicker io. - -Wed Aug 12 13:41:18 1992 Michael Widenius (monty@bitch) - - * Added new function get_copy_of_memory for combined malloc/copy. - * Splitted my_malloc to three files. - -Thu Jan 23 22:02:37 1992 Michael Widenius (monty at LYNX) - - * Added range-checks and aligned checks on ptrs to - safe_malloc:free and safe_malloc:realloc to catch more - error nicely without core-dumps. - -Wed Nov 13 01:52:18 1991 Michael Widenius (monty at LYNX) - - * Added use of mysys as a shared library. - -Sat Nov 9 14:38:21 1991 Michael Widenius (monty at LYNX) - - * Added expand of ~username to unpack_dirname. - -Tue Sep 17 21:15:08 1991 Michael Widenius (monty at LYNX) - - * Don't free null-pointers if passed to my_free - -Fri May 17 20:11:27 1991 Michael Widenius (monty at LYNX) - - * Changed all char * to string. (Can't change const char * because - of bug in C-definition. - -Tue Apr 30 01:32:56 1991 Michael Widenius (monty at LYNX) - - * my_path now examines environment for posix variable "_" if - progname is given and has no path. - -Mon Apr 22 16:12:56 1991 Michael Widenius (monty at LYNX) - - * Added function my_load_path() to fix path to a hard-path. - -Mon Apr 15 22:08:58 1991 Michael Widenius (monty at LYNX) - - * Added more info on DBUG-stream when freeing unallocated data. - -Wed Apr 3 18:41:28 1991 Michael Widenius (monty at LYNX) - - * Added global flag sf_malloc_no_sanity to make it possibly - to avoid sanity-checks in right code with uses malloc a lot. - -Tue Mar 26 15:09:45 1991 Mikael WIDENIUS (monty at panther) - - * Made soundex look nicer - -Sat Mar 23 10:49:49 1991 Michael Widenius (monty at LYNX) - - * Added init of alarm variables to skip some warnings from gcc. - -Tue Mar 5 16:50:34 1991 Michael Widenius (monty at LYNX) - - * Our qsort now only test if compare() function returns >= 0 - and is optimized for compare() returning > 0. - -Fri Nov 23 23:53:46 1990 Michael Widenius (monty at LYNX) - - * Added function my_set_alarm_variable to get a variable set - on some time. - my_alarm.h added for functions who want to print stat after - a given time or after a number of loops. - Changed my_lock to use new function and use defines in my_alarm.h - -Mon Oct 1 13:16:15 1990 Michael Widenius (monty at LYNX) - - * Added use of asynchronic io in read_cash_record(). - * Added write_cash and flush_write_cash to record cashing. - -Sun Sep 16 22:05:25 1990 Michael Widenius (monty at LYNX) - - * Added optional alarm to my_lock if one has FCNTL_LOCK. Added new - defines to my_sys.h. - -Mon Aug 27 22:20:38 1990 Michael Widenius (monty at lynx) - - * my_end() now can print output about executed program. - * Added parameter-defines for my_end in my_sys.h - -Sun Apr 1 23:29:47 1990 Monty (monty at monty) - - * Changed mf_keydisk.c to have separate functions for read and write. - Read can now return pointer to intern key-buffer to skip - unessessary memcpy-s. - -Fri Mar 23 23:03:39 1990 Monty (monty at monty) - - * function test_if_hard_pathname() added in dirname.c - * my_getwd now only saves changed current dir if dir is a - hard pathname. - * changed my_path() to use test_if_hard_pathname() - -Thu Mar 1 14:47:59 1990 Monty (monty at monty) - - * New function my_path(). - -Sat Feb 24 02:54:35 1990 Monty (monty at monty) - - * Added print of my_progname in my_mess.c - -Sun Feb 11 17:55:58 1990 David Axmark (davida at isil) - - * Concatenated libarys my_func and my_sys because of to much - crosswise dependencies. - * Fixed varagrs code in mf_fixadr.c - -Mon Dec 4 17:36:16 1989 Monty (monty at monty) - - * Changed safemalloc() to use my_message() if out of memory and - to check MY_WME if we want this error-messages. - * Changed my_setwd() to use dos_setdrive() insted of system(). - -Wed Oct 25 02:56:07 1989 Monty (monty at monty) - - * Changed my_mktmp1() to work like tempnam() with default dirname. - * Changed name of my_mktmp1.c to my_tempnam.c - -Thu Oct 19 16:39:27 1989 David Axmark (davida at isil) - - * Removed libary mysysnc. Instead added a hook to my_error that - can call my_message if needed. - -Thu Oct 5 01:33:29 1989 David Axmark (davida at isil) - - * Use MY_SEEK_{SET,CUR,END} as arguments to my_seek - - * Added a a array of structs that holds properties of open files. - Removed include file extras.h - -Wed Jun 21 01:34:04 1989 Monty (monty at monty) - - * Added two new malloc-functions: my_once_alloc() and - my_once_free(). These give easyer and quicker startup. - -Mon May 22 14:03:44 1989 Monty (monty at monty) - - * Fixed my_getwd and my_setwd so they work. - * Added extern variabel curr_char[] with is set to current - directory after my_getwd() or my_setwd(); - -Mon Jan 23 03:38:50 1989 Monty (monty at monty) - - * Changed my_chsize to check if NO_CHSIZE is defined. If new file - should be shorter it fills unused part with null. - * Changed my_lock to not check for arg 0 (Functions should use - LK_TO_EOF to lock all file. - -Tue Dec 6 15:09:44 1988 Monty (monty at monty) - - * Added DBUG_PRINT if error in my_seek. - -Mon Dec 5 15:58:48 1988 Monty (monty at monty) - - * Added DBUG_PRINT if not all byte read/written in my_read(), - my_fread(), my_write() and my_fwrite(); - -Sat Dec 3 01:48:03 1988 Monty (monty at monty) - - * Fixed bug in Makefile; quick did't work. - * Changed safemalloc to use bmove, bfill and memcpy when handling - memoryblocks. - -Fri Dec 2 03:29:21 1988 Monty (monty at monty) - - * Added more defines under MEMORY in my_func.h - * Added functions to llib-lmysys. - * Removed RCS/* files and installed ewerything as stable. - (Because errors in old RCS-files. - -Wed Nov 9 00:32:33 1988 Monty (monty at monty) - - * Changed realloc for MSDOS; Previous version freed old block on - * error, new version (of compiler) dosn't. - -Wed Oct 26 21:07:27 1988 Monty (monty at monty) - - * Fixed missing updateing of my_stream_opened; diff --git a/dep/mysqllite/mysys/array.c b/dep/mysqllite/mysys/array.c deleted file mode 100644 index 70c7a59aa3a..00000000000 --- a/dep/mysqllite/mysys/array.c +++ /dev/null @@ -1,383 +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 */ - -/* Handling of arrays that can grow dynamicly. */ - -#include "mysys_priv.h" -#include "m_string.h" - -/* - Initiate dynamic array - - SYNOPSIS - init_dynamic_array2() - array Pointer to an array - element_size Size of element - init_buffer Initial buffer pointer - init_alloc Number of initial elements - alloc_increment Increment for adding new elements - - DESCRIPTION - init_dynamic_array() initiates array and allocate space for - init_alloc eilements. - Array is usable even if space allocation failed, hence, the - function never returns TRUE. - Static buffers must begin immediately after the array structure. - - RETURN VALUE - FALSE Ok -*/ - -my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size, - void *init_buffer, uint init_alloc, - uint alloc_increment) -{ - DBUG_ENTER("init_dynamic_array"); - if (!alloc_increment) - { - alloc_increment=max((8192-MALLOC_OVERHEAD)/element_size,16); - if (init_alloc > 8 && alloc_increment > init_alloc * 2) - alloc_increment=init_alloc*2; - } - - if (!init_alloc) - { - init_alloc=alloc_increment; - init_buffer= 0; - } - array->elements=0; - array->max_element=init_alloc; - array->alloc_increment=alloc_increment; - array->size_of_element=element_size; - if ((array->buffer= init_buffer)) - DBUG_RETURN(FALSE); - /* - Since the dynamic array is usable even if allocation fails here malloc - should not throw an error - */ - if (!(array->buffer= (uchar*) my_malloc(element_size*init_alloc, MYF(0)))) - array->max_element=0; - DBUG_RETURN(FALSE); -} - -my_bool init_dynamic_array(DYNAMIC_ARRAY *array, uint element_size, - uint init_alloc, uint alloc_increment) -{ - /* placeholder to preserve ABI */ - return my_init_dynamic_array_ci(array, element_size, init_alloc, - alloc_increment); -} -/* - Insert element at the end of array. Allocate memory if needed. - - SYNOPSIS - insert_dynamic() - array - element - - RETURN VALUE - TRUE Insert failed - FALSE Ok -*/ - -my_bool insert_dynamic(DYNAMIC_ARRAY *array, uchar* element) -{ - uchar* buffer; - if (array->elements == array->max_element) - { /* Call only when nessesary */ - if (!(buffer=alloc_dynamic(array))) - return TRUE; - } - else - { - buffer=array->buffer+(array->elements * array->size_of_element); - array->elements++; - } - memcpy(buffer,element,(size_t) array->size_of_element); - return FALSE; -} - - -/* - Alloc space for next element(s) - - SYNOPSIS - alloc_dynamic() - array - - DESCRIPTION - alloc_dynamic() checks if there is empty space for at least - one element if not tries to allocate space for alloc_increment - elements at the end of array. - - RETURN VALUE - pointer Pointer to empty space for element - 0 Error -*/ - -uchar *alloc_dynamic(DYNAMIC_ARRAY *array) -{ - if (array->elements == array->max_element) - { - char *new_ptr; - if (array->buffer == (uchar *)(array + 1)) - { - /* - In this senerio, the buffer is statically preallocated, - so we have to create an all-new malloc since we overflowed - */ - if (!(new_ptr= (char *) my_malloc((array->max_element+ - array->alloc_increment) * - array->size_of_element, - MYF(MY_WME)))) - return 0; - memcpy(new_ptr, array->buffer, - array->elements * array->size_of_element); - } - else - if (!(new_ptr=(char*) my_realloc(array->buffer,(array->max_element+ - array->alloc_increment)* - array->size_of_element, - MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) - return 0; - array->buffer= (uchar*) new_ptr; - array->max_element+=array->alloc_increment; - } - return array->buffer+(array->elements++ * array->size_of_element); -} - - -/* - Pop last element from array. - - SYNOPSIS - pop_dynamic() - array - - RETURN VALUE - pointer Ok - 0 Array is empty -*/ - -uchar *pop_dynamic(DYNAMIC_ARRAY *array) -{ - if (array->elements) - return array->buffer+(--array->elements * array->size_of_element); - return 0; -} - -/* - Replace element in array with given element and index - - SYNOPSIS - set_dynamic() - array - element Element to be inserted - idx Index where element is to be inserted - - DESCRIPTION - set_dynamic() replaces element in array. - If idx > max_element insert new element. Allocate memory if needed. - - RETURN VALUE - TRUE Idx was out of range and allocation of new memory failed - FALSE Ok -*/ - -my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx) -{ - if (idx >= array->elements) - { - if (idx >= array->max_element && allocate_dynamic(array, idx)) - return TRUE; - bzero((uchar*) (array->buffer+array->elements*array->size_of_element), - (idx - array->elements)*array->size_of_element); - array->elements=idx+1; - } - memcpy(array->buffer+(idx * array->size_of_element),element, - (size_t) array->size_of_element); - return FALSE; -} - - -/* - Ensure that dynamic array has enough elements - - SYNOPSIS - allocate_dynamic() - array - max_elements Numbers of elements that is needed - - NOTES - Any new allocated element are NOT initialized - - RETURN VALUE - FALSE Ok - TRUE Allocation of new memory failed -*/ - -my_bool allocate_dynamic(DYNAMIC_ARRAY *array, uint max_elements) -{ - if (max_elements >= array->max_element) - { - uint size; - uchar *new_ptr; - size= (max_elements + array->alloc_increment)/array->alloc_increment; - size*= array->alloc_increment; - if (array->buffer == (uchar *)(array + 1)) - { - /* - In this senerio, the buffer is statically preallocated, - so we have to create an all-new malloc since we overflowed - */ - if (!(new_ptr= (uchar *) my_malloc(size * - array->size_of_element, - MYF(MY_WME)))) - return 0; - memcpy(new_ptr, array->buffer, - array->elements * array->size_of_element); - } - else - - - if (!(new_ptr= (uchar*) my_realloc(array->buffer,size* - array->size_of_element, - MYF(MY_WME | MY_ALLOW_ZERO_PTR)))) - return TRUE; - array->buffer= new_ptr; - array->max_element= size; - } - return FALSE; -} - - -/* - Get an element from array by given index - - SYNOPSIS - get_dynamic() - array - uchar* Element to be returned. If idx > elements contain zeroes. - idx Index of element wanted. -*/ - -void get_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx) -{ - if (idx >= array->elements) - { - DBUG_PRINT("warning",("To big array idx: %d, array size is %d", - idx,array->elements)); - bzero(element,array->size_of_element); - return; - } - memcpy(element,array->buffer+idx*array->size_of_element, - (size_t) array->size_of_element); -} - - -/* - Empty array by freeing all memory - - SYNOPSIS - delete_dynamic() - array Array to be deleted -*/ - -void delete_dynamic(DYNAMIC_ARRAY *array) -{ - /* - Just mark as empty if we are using a static buffer - */ - if (array->buffer == (uchar *)(array + 1)) - array->elements= 0; - else - if (array->buffer) - { - my_free(array->buffer); - array->buffer=0; - array->elements=array->max_element=0; - } -} - -/* - Delete element by given index - - SYNOPSIS - delete_dynamic_element() - array - idx Index of element to be deleted -*/ - -void delete_dynamic_element(DYNAMIC_ARRAY *array, uint idx) -{ - char *ptr= (char*) array->buffer+array->size_of_element*idx; - array->elements--; - memmove(ptr,ptr+array->size_of_element, - (array->elements-idx)*array->size_of_element); -} - - -/* - Free unused memory - - SYNOPSIS - freeze_size() - array Array to be freed - -*/ - -void freeze_size(DYNAMIC_ARRAY *array) -{ - uint elements=max(array->elements,1); - - /* - Do nothing if we are using a static buffer - */ - if (array->buffer == (uchar *)(array + 1)) - return; - - if (array->buffer && array->max_element != elements) - { - array->buffer=(uchar*) my_realloc(array->buffer, - elements*array->size_of_element, - MYF(MY_WME)); - 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, uchar* element) -{ - size_t 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/dep/mysqllite/mysys/base64.c b/dep/mysqllite/mysys/base64.c deleted file mode 100644 index ab66715c929..00000000000 --- a/dep/mysqllite/mysys/base64.c +++ /dev/null @@ -1,311 +0,0 @@ -/* Copyright (C) 2003 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> /* strchr() */ -#include <m_ctype.h> /* my_isspace() */ -#include <base64.h> - -#ifndef MAIN - -static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789+/"; - - -int -base64_needed_encoded_length(int length_of_data) -{ - int nb_base64_chars; - nb_base64_chars= (length_of_data + 2) / 3 * 4; - - return - nb_base64_chars + /* base64 char incl padding */ - (nb_base64_chars - 1)/ 76 + /* newlines */ - 1; /* NUL termination of string */ -} - - -int -base64_needed_decoded_length(int length_of_encoded_data) -{ - return (int) ceil(length_of_encoded_data * 3 / 4); -} - - -/* - Encode a data as base64. - - Note: We require that dst is pre-allocated to correct size. - See base64_needed_encoded_length(). -*/ - -int -base64_encode(const void *src, size_t src_len, char *dst) -{ - const unsigned char *s= (const unsigned char*)src; - size_t i= 0; - size_t len= 0; - - for (; i < src_len; len += 4) - { - unsigned c; - - if (len == 76) - { - len= 0; - *dst++= '\n'; - } - - c= s[i++]; - c <<= 8; - - if (i < src_len) - c += s[i]; - c <<= 8; - i++; - - if (i < src_len) - c += s[i]; - i++; - - *dst++= base64_table[(c >> 18) & 0x3f]; - *dst++= base64_table[(c >> 12) & 0x3f]; - - if (i > (src_len + 1)) - *dst++= '='; - else - *dst++= base64_table[(c >> 6) & 0x3f]; - - if (i > src_len) - *dst++= '='; - else - *dst++= base64_table[(c >> 0) & 0x3f]; - } - *dst= '\0'; - - return 0; -} - - -static inline uint -pos(unsigned char c) -{ - return (uint) (strchr(base64_table, c) - base64_table); -} - - -#define SKIP_SPACE(src, i, size) \ -{ \ - while (i < size && my_isspace(&my_charset_latin1, * src)) \ - { \ - i++; \ - src++; \ - } \ - if (i == size) \ - { \ - break; \ - } \ -} - - -/* - Decode a base64 string - - 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. - - 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_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 < len) - { - unsigned c= 0; - size_t mark= 0; - - SKIP_SPACE(src, i, len); - - c += pos(*src++); - c <<= 6; - i++; - - SKIP_SPACE(src, i, len); - - c += pos(*src++); - c <<= 6; - i++; - - SKIP_SPACE(src, i, len); - - if (*src != '=') - c += pos(*src++); - else - { - src += 2; /* There should be two bytes padding */ - i= len; - mark= 2; - c <<= 6; - goto end; - } - c <<= 6; - i++; - - SKIP_SPACE(src, i, len); - - if (*src != '=') - c += pos(*src++); - else - { - src += 1; /* There should be one byte padding */ - i= len; - mark= 1; - goto end; - } - i++; - - end: - b[0]= (c >> 16) & 0xff; - b[1]= (c >> 8) & 0xff; - b[2]= (c >> 0) & 0xff; - - for (j=0; j<3-mark; j++) - *d++= b[j]; - } - - 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 : (int) (d - dst_base); -} - - -#else /* MAIN */ - -#define require(b) { \ - if (!(b)) { \ - printf("Require failed at %s:%d\n", __FILE__, __LINE__); \ - abort(); \ - } \ -} - - -int -main(void) -{ - int i; - size_t j; - size_t k, l; - size_t dst_len; - size_t needed_length; - - for (i= 0; i < 500; i++) - { - /* Create source data */ - const size_t src_len= rand() % 1000 + 1; - - char * src= (char *) malloc(src_len); - char * s= src; - char * str; - char * dst; - - require(src); - for (j= 0; j<src_len; j++) - { - char c= rand(); - *s++= c; - } - - /* Encode */ - needed_length= base64_needed_encoded_length(src_len); - str= (char *) malloc(needed_length); - require(str); - for (k= 0; k < needed_length; k++) - str[k]= 0xff; /* Fill memory to check correct NUL termination */ - require(base64_encode(src, src_len, str) == 0); - require(needed_length == strlen(str) + 1); - - /* Decode */ - dst= (char *) malloc(base64_needed_decoded_length(strlen(str))); - require(dst); - dst_len= base64_decode(str, strlen(str), dst, NULL); - require(dst_len == src_len); - - if (memcmp(src, dst, src_len) != 0) - { - printf(" --------- src --------- --------- dst ---------\n"); - for (k= 0; k<src_len; k+=8) - { - printf("%.4x ", (uint) k); - for (l=0; l<8 && k+l<src_len; l++) - { - unsigned char c= src[k+l]; - printf("%.2x ", (unsigned)c); - } - - printf(" "); - - for (l=0; l<8 && k+l<dst_len; l++) - { - unsigned char c= dst[k+l]; - printf("%.2x ", (unsigned)c); - } - printf("\n"); - } - printf("src length: %.8x, dst length: %.8x\n", - (uint) src_len, (uint) dst_len); - require(0); - } - } - printf("Test succeeded.\n"); - return 0; -} - -#endif diff --git a/dep/mysqllite/mysys/charset-def.c b/dep/mysqllite/mysys/charset-def.c deleted file mode 100644 index 9089347f002..00000000000 --- a/dep/mysqllite/mysys/charset-def.c +++ /dev/null @@ -1,354 +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 all compiled character sets into the client - If a client don't want to use all of them, he can define his own - init_compiled_charsets() that only adds those that he wants -*/ - -#ifdef HAVE_UCA_COLLATIONS - -#ifdef HAVE_CHARSET_ucs2 -extern CHARSET_INFO my_charset_ucs2_icelandic_uca_ci; -extern CHARSET_INFO my_charset_ucs2_latvian_uca_ci; -extern CHARSET_INFO my_charset_ucs2_romanian_uca_ci; -extern CHARSET_INFO my_charset_ucs2_slovenian_uca_ci; -extern CHARSET_INFO my_charset_ucs2_polish_uca_ci; -extern CHARSET_INFO my_charset_ucs2_estonian_uca_ci; -extern CHARSET_INFO my_charset_ucs2_spanish_uca_ci; -extern CHARSET_INFO my_charset_ucs2_swedish_uca_ci; -extern CHARSET_INFO my_charset_ucs2_turkish_uca_ci; -extern CHARSET_INFO my_charset_ucs2_czech_uca_ci; -extern CHARSET_INFO my_charset_ucs2_danish_uca_ci; -extern CHARSET_INFO my_charset_ucs2_lithuanian_uca_ci; -extern CHARSET_INFO my_charset_ucs2_slovak_uca_ci; -extern CHARSET_INFO my_charset_ucs2_spanish2_uca_ci; -extern CHARSET_INFO my_charset_ucs2_roman_uca_ci; -extern CHARSET_INFO my_charset_ucs2_persian_uca_ci; -extern CHARSET_INFO my_charset_ucs2_esperanto_uca_ci; -extern CHARSET_INFO my_charset_ucs2_hungarian_uca_ci; -extern CHARSET_INFO my_charset_ucs2_sinhala_uca_ci; -#endif - - -#ifdef HAVE_CHARSET_utf32 -extern CHARSET_INFO my_charset_utf32_icelandic_uca_ci; -extern CHARSET_INFO my_charset_utf32_latvian_uca_ci; -extern CHARSET_INFO my_charset_utf32_romanian_uca_ci; -extern CHARSET_INFO my_charset_utf32_slovenian_uca_ci; -extern CHARSET_INFO my_charset_utf32_polish_uca_ci; -extern CHARSET_INFO my_charset_utf32_estonian_uca_ci; -extern CHARSET_INFO my_charset_utf32_spanish_uca_ci; -extern CHARSET_INFO my_charset_utf32_swedish_uca_ci; -extern CHARSET_INFO my_charset_utf32_turkish_uca_ci; -extern CHARSET_INFO my_charset_utf32_czech_uca_ci; -extern CHARSET_INFO my_charset_utf32_danish_uca_ci; -extern CHARSET_INFO my_charset_utf32_lithuanian_uca_ci; -extern CHARSET_INFO my_charset_utf32_slovak_uca_ci; -extern CHARSET_INFO my_charset_utf32_spanish2_uca_ci; -extern CHARSET_INFO my_charset_utf32_roman_uca_ci; -extern CHARSET_INFO my_charset_utf32_persian_uca_ci; -extern CHARSET_INFO my_charset_utf32_esperanto_uca_ci; -extern CHARSET_INFO my_charset_utf32_hungarian_uca_ci; -extern CHARSET_INFO my_charset_utf32_sinhala_uca_ci; -#endif /* HAVE_CHARSET_utf32 */ - - -#ifdef HAVE_CHARSET_utf16 -extern CHARSET_INFO my_charset_utf16_icelandic_uca_ci; -extern CHARSET_INFO my_charset_utf16_latvian_uca_ci; -extern CHARSET_INFO my_charset_utf16_romanian_uca_ci; -extern CHARSET_INFO my_charset_utf16_slovenian_uca_ci; -extern CHARSET_INFO my_charset_utf16_polish_uca_ci; -extern CHARSET_INFO my_charset_utf16_estonian_uca_ci; -extern CHARSET_INFO my_charset_utf16_spanish_uca_ci; -extern CHARSET_INFO my_charset_utf16_swedish_uca_ci; -extern CHARSET_INFO my_charset_utf16_turkish_uca_ci; -extern CHARSET_INFO my_charset_utf16_czech_uca_ci; -extern CHARSET_INFO my_charset_utf16_danish_uca_ci; -extern CHARSET_INFO my_charset_utf16_lithuanian_uca_ci; -extern CHARSET_INFO my_charset_utf16_slovak_uca_ci; -extern CHARSET_INFO my_charset_utf16_spanish2_uca_ci; -extern CHARSET_INFO my_charset_utf16_roman_uca_ci; -extern CHARSET_INFO my_charset_utf16_persian_uca_ci; -extern CHARSET_INFO my_charset_utf16_esperanto_uca_ci; -extern CHARSET_INFO my_charset_utf16_hungarian_uca_ci; -extern CHARSET_INFO my_charset_utf16_sinhala_uca_ci; -#endif /* HAVE_CHARSET_utf16 */ - - -#ifdef HAVE_CHARSET_utf8 -extern CHARSET_INFO my_charset_utf8_icelandic_uca_ci; -extern CHARSET_INFO my_charset_utf8_latvian_uca_ci; -extern CHARSET_INFO my_charset_utf8_romanian_uca_ci; -extern CHARSET_INFO my_charset_utf8_slovenian_uca_ci; -extern CHARSET_INFO my_charset_utf8_polish_uca_ci; -extern CHARSET_INFO my_charset_utf8_estonian_uca_ci; -extern CHARSET_INFO my_charset_utf8_spanish_uca_ci; -extern CHARSET_INFO my_charset_utf8_swedish_uca_ci; -extern CHARSET_INFO my_charset_utf8_turkish_uca_ci; -extern CHARSET_INFO my_charset_utf8_czech_uca_ci; -extern CHARSET_INFO my_charset_utf8_danish_uca_ci; -extern CHARSET_INFO my_charset_utf8_lithuanian_uca_ci; -extern CHARSET_INFO my_charset_utf8_slovak_uca_ci; -extern CHARSET_INFO my_charset_utf8_spanish2_uca_ci; -extern CHARSET_INFO my_charset_utf8_roman_uca_ci; -extern CHARSET_INFO my_charset_utf8_persian_uca_ci; -extern CHARSET_INFO my_charset_utf8_esperanto_uca_ci; -extern CHARSET_INFO my_charset_utf8_hungarian_uca_ci; -extern CHARSET_INFO my_charset_utf8_sinhala_uca_ci; -#ifdef HAVE_UTF8_GENERAL_CS -extern CHARSET_INFO my_charset_utf8_general_cs; -#endif -#endif - -#ifdef HAVE_CHARSET_utf8mb4 -extern CHARSET_INFO my_charset_utf8mb4_icelandic_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_latvian_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_romanian_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_slovenian_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_polish_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_estonian_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_spanish_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_swedish_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_turkish_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_czech_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_danish_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_lithuanian_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_slovak_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_spanish2_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_roman_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_persian_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_esperanto_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_hungarian_uca_ci; -extern CHARSET_INFO my_charset_utf8mb4_sinhala_uca_ci; -#endif /* HAVE_CHARSET_utf8mb4 */ - -#endif /* HAVE_UCA_COLLATIONS */ - -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); - add_compiled_collation(&my_charset_latin1_german2_ci); - -#ifdef HAVE_CHARSET_big5 - add_compiled_collation(&my_charset_big5_chinese_ci); - add_compiled_collation(&my_charset_big5_bin); -#endif - -#ifdef HAVE_CHARSET_cp1250 - add_compiled_collation(&my_charset_cp1250_czech_ci); -#endif - -#ifdef HAVE_CHARSET_cp932 - add_compiled_collation(&my_charset_cp932_japanese_ci); - add_compiled_collation(&my_charset_cp932_bin); -#endif - -#ifdef HAVE_CHARSET_latin2 - add_compiled_collation(&my_charset_latin2_czech_ci); -#endif - -#ifdef HAVE_CHARSET_eucjpms - add_compiled_collation(&my_charset_eucjpms_japanese_ci); - add_compiled_collation(&my_charset_eucjpms_bin); -#endif - -#ifdef HAVE_CHARSET_euckr - add_compiled_collation(&my_charset_euckr_korean_ci); - add_compiled_collation(&my_charset_euckr_bin); -#endif - -#ifdef HAVE_CHARSET_gb2312 - add_compiled_collation(&my_charset_gb2312_chinese_ci); - add_compiled_collation(&my_charset_gb2312_bin); -#endif - -#ifdef HAVE_CHARSET_gbk - add_compiled_collation(&my_charset_gbk_chinese_ci); - add_compiled_collation(&my_charset_gbk_bin); -#endif - -#ifdef HAVE_CHARSET_sjis - add_compiled_collation(&my_charset_sjis_japanese_ci); - add_compiled_collation(&my_charset_sjis_bin); -#endif - -#ifdef HAVE_CHARSET_tis620 - add_compiled_collation(&my_charset_tis620_thai_ci); - add_compiled_collation(&my_charset_tis620_bin); -#endif - -#ifdef HAVE_CHARSET_ucs2 - add_compiled_collation(&my_charset_ucs2_general_ci); - add_compiled_collation(&my_charset_ucs2_bin); -#ifdef HAVE_UCA_COLLATIONS - add_compiled_collation(&my_charset_ucs2_unicode_ci); - add_compiled_collation(&my_charset_ucs2_icelandic_uca_ci); - add_compiled_collation(&my_charset_ucs2_latvian_uca_ci); - add_compiled_collation(&my_charset_ucs2_romanian_uca_ci); - add_compiled_collation(&my_charset_ucs2_slovenian_uca_ci); - add_compiled_collation(&my_charset_ucs2_polish_uca_ci); - add_compiled_collation(&my_charset_ucs2_estonian_uca_ci); - add_compiled_collation(&my_charset_ucs2_spanish_uca_ci); - add_compiled_collation(&my_charset_ucs2_swedish_uca_ci); - add_compiled_collation(&my_charset_ucs2_turkish_uca_ci); - add_compiled_collation(&my_charset_ucs2_czech_uca_ci); - add_compiled_collation(&my_charset_ucs2_danish_uca_ci); - add_compiled_collation(&my_charset_ucs2_lithuanian_uca_ci); - add_compiled_collation(&my_charset_ucs2_slovak_uca_ci); - add_compiled_collation(&my_charset_ucs2_spanish2_uca_ci); - add_compiled_collation(&my_charset_ucs2_roman_uca_ci); - add_compiled_collation(&my_charset_ucs2_persian_uca_ci); - add_compiled_collation(&my_charset_ucs2_esperanto_uca_ci); - add_compiled_collation(&my_charset_ucs2_hungarian_uca_ci); - add_compiled_collation(&my_charset_ucs2_sinhala_uca_ci); -#endif -#endif - -#ifdef HAVE_CHARSET_ujis - add_compiled_collation(&my_charset_ujis_japanese_ci); - add_compiled_collation(&my_charset_ujis_bin); -#endif - -#ifdef HAVE_CHARSET_utf8 - add_compiled_collation(&my_charset_utf8_general_ci); - add_compiled_collation(&my_charset_utf8_bin); -#ifdef HAVE_UTF8_GENERAL_CS - add_compiled_collation(&my_charset_utf8_general_cs); -#endif -#ifdef HAVE_UCA_COLLATIONS - add_compiled_collation(&my_charset_utf8_unicode_ci); - add_compiled_collation(&my_charset_utf8_icelandic_uca_ci); - add_compiled_collation(&my_charset_utf8_latvian_uca_ci); - add_compiled_collation(&my_charset_utf8_romanian_uca_ci); - add_compiled_collation(&my_charset_utf8_slovenian_uca_ci); - add_compiled_collation(&my_charset_utf8_polish_uca_ci); - add_compiled_collation(&my_charset_utf8_estonian_uca_ci); - add_compiled_collation(&my_charset_utf8_spanish_uca_ci); - add_compiled_collation(&my_charset_utf8_swedish_uca_ci); - add_compiled_collation(&my_charset_utf8_turkish_uca_ci); - add_compiled_collation(&my_charset_utf8_czech_uca_ci); - add_compiled_collation(&my_charset_utf8_danish_uca_ci); - add_compiled_collation(&my_charset_utf8_lithuanian_uca_ci); - add_compiled_collation(&my_charset_utf8_slovak_uca_ci); - add_compiled_collation(&my_charset_utf8_spanish2_uca_ci); - add_compiled_collation(&my_charset_utf8_roman_uca_ci); - add_compiled_collation(&my_charset_utf8_persian_uca_ci); - add_compiled_collation(&my_charset_utf8_esperanto_uca_ci); - add_compiled_collation(&my_charset_utf8_hungarian_uca_ci); - add_compiled_collation(&my_charset_utf8_sinhala_uca_ci); -#endif -#endif /* HAVE_CHARSET_utf8 */ - - -#ifdef HAVE_CHARSET_utf8mb4 - add_compiled_collation(&my_charset_utf8mb4_general_ci); - add_compiled_collation(&my_charset_utf8mb4_bin); -#ifdef HAVE_UCA_COLLATIONS - add_compiled_collation(&my_charset_utf8mb4_unicode_ci); - add_compiled_collation(&my_charset_utf8mb4_icelandic_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_latvian_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_romanian_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_slovenian_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_polish_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_estonian_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_spanish_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_swedish_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_turkish_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_czech_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_danish_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_lithuanian_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_slovak_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_spanish2_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_roman_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_persian_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_esperanto_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_hungarian_uca_ci); - add_compiled_collation(&my_charset_utf8mb4_sinhala_uca_ci); -#endif /* HAVE_UCA_COLLATIONS */ -#endif /* HAVE_CHARSET_utf8mb4 */ - - -#ifdef HAVE_CHARSET_utf16 - add_compiled_collation(&my_charset_utf16_general_ci); - add_compiled_collation(&my_charset_utf16_bin); -#ifdef HAVE_UCA_COLLATIONS - add_compiled_collation(&my_charset_utf16_unicode_ci); - add_compiled_collation(&my_charset_utf16_icelandic_uca_ci); - add_compiled_collation(&my_charset_utf16_latvian_uca_ci); - add_compiled_collation(&my_charset_utf16_romanian_uca_ci); - add_compiled_collation(&my_charset_utf16_slovenian_uca_ci); - add_compiled_collation(&my_charset_utf16_polish_uca_ci); - add_compiled_collation(&my_charset_utf16_estonian_uca_ci); - add_compiled_collation(&my_charset_utf16_spanish_uca_ci); - add_compiled_collation(&my_charset_utf16_swedish_uca_ci); - add_compiled_collation(&my_charset_utf16_turkish_uca_ci); - add_compiled_collation(&my_charset_utf16_czech_uca_ci); - add_compiled_collation(&my_charset_utf16_danish_uca_ci); - add_compiled_collation(&my_charset_utf16_lithuanian_uca_ci); - add_compiled_collation(&my_charset_utf16_slovak_uca_ci); - add_compiled_collation(&my_charset_utf16_spanish2_uca_ci); - add_compiled_collation(&my_charset_utf16_roman_uca_ci); - add_compiled_collation(&my_charset_utf16_persian_uca_ci); - add_compiled_collation(&my_charset_utf16_esperanto_uca_ci); - add_compiled_collation(&my_charset_utf16_hungarian_uca_ci); - add_compiled_collation(&my_charset_utf16_sinhala_uca_ci); -#endif /* HAVE_UCA_COLLATIOINS */ -#endif /* HAVE_CHARSET_utf16 */ - - -#ifdef HAVE_CHARSET_utf32 - add_compiled_collation(&my_charset_utf32_general_ci); - add_compiled_collation(&my_charset_utf32_bin); -#ifdef HAVE_UCA_COLLATIONS - add_compiled_collation(&my_charset_utf32_unicode_ci); - add_compiled_collation(&my_charset_utf32_icelandic_uca_ci); - add_compiled_collation(&my_charset_utf32_latvian_uca_ci); - add_compiled_collation(&my_charset_utf32_romanian_uca_ci); - add_compiled_collation(&my_charset_utf32_slovenian_uca_ci); - add_compiled_collation(&my_charset_utf32_polish_uca_ci); - add_compiled_collation(&my_charset_utf32_estonian_uca_ci); - add_compiled_collation(&my_charset_utf32_spanish_uca_ci); - add_compiled_collation(&my_charset_utf32_swedish_uca_ci); - add_compiled_collation(&my_charset_utf32_turkish_uca_ci); - add_compiled_collation(&my_charset_utf32_czech_uca_ci); - add_compiled_collation(&my_charset_utf32_danish_uca_ci); - add_compiled_collation(&my_charset_utf32_lithuanian_uca_ci); - add_compiled_collation(&my_charset_utf32_slovak_uca_ci); - add_compiled_collation(&my_charset_utf32_spanish2_uca_ci); - add_compiled_collation(&my_charset_utf32_roman_uca_ci); - add_compiled_collation(&my_charset_utf32_persian_uca_ci); - add_compiled_collation(&my_charset_utf32_esperanto_uca_ci); - add_compiled_collation(&my_charset_utf32_hungarian_uca_ci); - add_compiled_collation(&my_charset_utf32_sinhala_uca_ci); -#endif /* HAVE_UCA_COLLATIONS */ -#endif /* HAVE_CHARSET_utf32 */ - - /* Copy compiled charsets */ - for (cs=compiled_charsets; cs->name; cs++) - add_compiled_collation(cs); - - return FALSE; -} diff --git a/dep/mysqllite/mysys/charset.c b/dep/mysqllite/mysys/charset.c deleted file mode 100644 index 167d6b8ff6e..00000000000 --- a/dep/mysqllite/mysys/charset.c +++ /dev/null @@ -1,937 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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" -#include <m_ctype.h> -#include <m_string.h> -#include <my_dir.h> -#include <my_xml.h> - - -/* - The code below implements this functionality: - - - Initializing charset related structures - - Loading dynamic charsets - - Searching for a proper CHARSET_INFO - using charset name, collation name or collation ID - - Setting server default character set -*/ - -my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2) -{ - return ((cs1 == cs2) || !strcmp(cs1->csname,cs2->csname)); -} - - -static uint -get_collation_number_internal(const char *name) -{ - CHARSET_INFO **cs; - for (cs= all_charsets; - cs < all_charsets + array_elements(all_charsets); - cs++) - { - if ( cs[0] && cs[0]->name && - !my_strcasecmp(&my_charset_latin1, cs[0]->name, name)) - return cs[0]->number; - } - return 0; -} - - -static my_bool init_state_maps(CHARSET_INFO *cs) -{ - uint i; - uchar *state_map; - uchar *ident_map; - - if (!(cs->state_map= (uchar*) my_once_alloc(256, MYF(MY_WME)))) - return 1; - - if (!(cs->ident_map= (uchar*) my_once_alloc(256, MYF(MY_WME)))) - return 1; - - state_map= cs->state_map; - ident_map= cs->ident_map; - - /* Fill state_map with states to get a faster parser */ - for (i=0; i < 256 ; i++) - { - if (my_isalpha(cs,i)) - state_map[i]=(uchar) MY_LEX_IDENT; - else if (my_isdigit(cs,i)) - state_map[i]=(uchar) MY_LEX_NUMBER_IDENT; -#if defined(USE_MB) && defined(USE_MB_IDENT) - else if (my_mbcharlen(cs, i)>1) - state_map[i]=(uchar) MY_LEX_IDENT; -#endif - else if (my_isspace(cs,i)) - state_map[i]=(uchar) MY_LEX_SKIP; - else - state_map[i]=(uchar) MY_LEX_CHAR; - } - state_map[(uchar)'_']=state_map[(uchar)'$']=(uchar) MY_LEX_IDENT; - state_map[(uchar)'\'']=(uchar) MY_LEX_STRING; - state_map[(uchar)'.']=(uchar) MY_LEX_REAL_OR_POINT; - state_map[(uchar)'>']=state_map[(uchar)'=']=state_map[(uchar)'!']= (uchar) MY_LEX_CMP_OP; - state_map[(uchar)'<']= (uchar) MY_LEX_LONG_CMP_OP; - state_map[(uchar)'&']=state_map[(uchar)'|']=(uchar) MY_LEX_BOOL; - state_map[(uchar)'#']=(uchar) MY_LEX_COMMENT; - state_map[(uchar)';']=(uchar) MY_LEX_SEMICOLON; - state_map[(uchar)':']=(uchar) MY_LEX_SET_VAR; - state_map[0]=(uchar) MY_LEX_EOL; - state_map[(uchar)'\\']= (uchar) MY_LEX_ESCAPE; - state_map[(uchar)'/']= (uchar) MY_LEX_LONG_COMMENT; - state_map[(uchar)'*']= (uchar) MY_LEX_END_LONG_COMMENT; - state_map[(uchar)'@']= (uchar) MY_LEX_USER_END; - state_map[(uchar) '`']= (uchar) MY_LEX_USER_VARIABLE_DELIMITER; - state_map[(uchar)'"']= (uchar) MY_LEX_STRING_OR_DELIMITER; - - /* - Create a second map to make it faster to find identifiers - */ - for (i=0; i < 256 ; i++) - { - ident_map[i]= (uchar) (state_map[i] == MY_LEX_IDENT || - state_map[i] == MY_LEX_NUMBER_IDENT); - } - - /* Special handling of hex and binary strings */ - state_map[(uchar)'x']= state_map[(uchar)'X']= (uchar) MY_LEX_IDENT_OR_HEX; - state_map[(uchar)'b']= state_map[(uchar)'B']= (uchar) MY_LEX_IDENT_OR_BIN; - state_map[(uchar)'n']= state_map[(uchar)'N']= (uchar) MY_LEX_IDENT_OR_NCHAR; - return 0; -} - - -static void simple_cs_init_functions(CHARSET_INFO *cs) -{ - if (cs->state & MY_CS_BINSORT) - cs->coll= &my_collation_8bit_bin_handler; - else - cs->coll= &my_collation_8bit_simple_ci_handler; - - cs->cset= &my_charset_8bit_handler; -} - - - -static int cs_copy_data(CHARSET_INFO *to, CHARSET_INFO *from) -{ - to->number= from->number ? from->number : to->number; - - if (from->csname) - if (!(to->csname= my_once_strdup(from->csname,MYF(MY_WME)))) - goto err; - - if (from->name) - if (!(to->name= my_once_strdup(from->name,MYF(MY_WME)))) - goto err; - - if (from->comment) - if (!(to->comment= my_once_strdup(from->comment,MYF(MY_WME)))) - goto err; - - if (from->ctype) - { - if (!(to->ctype= (uchar*) my_once_memdup((char*) from->ctype, - MY_CS_CTYPE_TABLE_SIZE, - MYF(MY_WME)))) - goto err; - if (init_state_maps(to)) - goto err; - } - if (from->to_lower) - if (!(to->to_lower= (uchar*) my_once_memdup((char*) from->to_lower, - MY_CS_TO_LOWER_TABLE_SIZE, - MYF(MY_WME)))) - goto err; - - if (from->to_upper) - if (!(to->to_upper= (uchar*) my_once_memdup((char*) from->to_upper, - MY_CS_TO_UPPER_TABLE_SIZE, - MYF(MY_WME)))) - goto err; - if (from->sort_order) - { - if (!(to->sort_order= (uchar*) my_once_memdup((char*) from->sort_order, - MY_CS_SORT_ORDER_TABLE_SIZE, - MYF(MY_WME)))) - goto err; - - } - if (from->tab_to_uni) - { - uint sz= MY_CS_TO_UNI_TABLE_SIZE*sizeof(uint16); - if (!(to->tab_to_uni= (uint16*) my_once_memdup((char*)from->tab_to_uni, - sz, MYF(MY_WME)))) - goto err; - } - if (from->tailoring) - if (!(to->tailoring= my_once_strdup(from->tailoring,MYF(MY_WME)))) - goto err; - - return 0; - -err: - return 1; -} - - - -static my_bool simple_cs_is_full(CHARSET_INFO *cs) -{ - return ((cs->csname && cs->tab_to_uni && cs->ctype && cs->to_upper && - cs->to_lower) && - (cs->number && cs->name && - (cs->sort_order || (cs->state & MY_CS_BINSORT) ))); -} - - -static void -copy_uca_collation(CHARSET_INFO *to, CHARSET_INFO *from) -{ - to->cset= from->cset; - to->coll= from->coll; - to->strxfrm_multiply= from->strxfrm_multiply; - to->min_sort_char= from->min_sort_char; - to->max_sort_char= from->max_sort_char; - to->mbminlen= from->mbminlen; - to->mbmaxlen= from->mbmaxlen; - to->state|= MY_CS_AVAILABLE | MY_CS_LOADED | - MY_CS_STRNXFRM | MY_CS_UNICODE; -} - - -static int add_collation(CHARSET_INFO *cs) -{ - if (cs->name && (cs->number || - (cs->number=get_collation_number_internal(cs->name))) && - cs->number < array_elements(all_charsets)) - { - if (!all_charsets[cs->number]) - { - if (!(all_charsets[cs->number]= - (CHARSET_INFO*) my_once_alloc(sizeof(CHARSET_INFO),MYF(0)))) - return MY_XML_ERROR; - bzero((void*)all_charsets[cs->number],sizeof(CHARSET_INFO)); - } - - if (cs->primary_number == cs->number) - cs->state |= MY_CS_PRIMARY; - - if (cs->binary_number == cs->number) - cs->state |= MY_CS_BINSORT; - - all_charsets[cs->number]->state|= cs->state; - - if (!(all_charsets[cs->number]->state & MY_CS_COMPILED)) - { - CHARSET_INFO *newcs= all_charsets[cs->number]; - if (cs_copy_data(all_charsets[cs->number],cs)) - return MY_XML_ERROR; - - newcs->caseup_multiply= newcs->casedn_multiply= 1; - - if (!strcmp(cs->csname,"ucs2") ) - { -#if defined(HAVE_CHARSET_ucs2) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_ucs2_unicode_ci); - newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; -#endif - } - else if (!strcmp(cs->csname, "utf8") || !strcmp(cs->csname, "utf8mb3")) - { -#if defined (HAVE_CHARSET_utf8) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_utf8_unicode_ci); - newcs->ctype= my_charset_utf8_unicode_ci.ctype; - if (init_state_maps(newcs)) - return MY_XML_ERROR; -#endif - } - else if (!strcmp(cs->csname, "utf8mb4")) - { -#if defined (HAVE_CHARSET_utf8mb4) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_utf8mb4_unicode_ci); - newcs->ctype= my_charset_utf8mb4_unicode_ci.ctype; - newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED; -#endif - } - else if (!strcmp(cs->csname, "utf16")) - { -#if defined (HAVE_CHARSET_utf16) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_utf16_unicode_ci); - newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; -#endif - } - else if (!strcmp(cs->csname, "utf32")) - { -#if defined (HAVE_CHARSET_utf32) && defined(HAVE_UCA_COLLATIONS) - copy_uca_collation(newcs, &my_charset_utf32_unicode_ci); - newcs->state|= MY_CS_AVAILABLE | MY_CS_LOADED | MY_CS_NONASCII; -#endif - } - else - { - uchar *sort_order= all_charsets[cs->number]->sort_order; - simple_cs_init_functions(all_charsets[cs->number]); - newcs->mbminlen= 1; - newcs->mbmaxlen= 1; - if (simple_cs_is_full(all_charsets[cs->number])) - { - all_charsets[cs->number]->state |= MY_CS_LOADED; - } - all_charsets[cs->number]->state|= MY_CS_AVAILABLE; - - /* - Check if case sensitive sort order: A < a < B. - We need MY_CS_FLAG for regex library, and for - case sensitivity flag for 5.0 client protocol, - to support isCaseSensitive() method in JDBC driver - */ - if (sort_order && sort_order['A'] < sort_order['a'] && - sort_order['a'] < sort_order['B']) - all_charsets[cs->number]->state|= MY_CS_CSSORT; - - if (my_charset_is_8bit_pure_ascii(all_charsets[cs->number])) - all_charsets[cs->number]->state|= MY_CS_PUREASCII; - if (!my_charset_is_ascii_compatible(cs)) - all_charsets[cs->number]->state|= MY_CS_NONASCII; - } - } - else - { - /* - We need the below to make get_charset_name() - and get_charset_number() working even if a - character set has not been really incompiled. - The above functions are used for example - in error message compiler extra/comp_err.c. - If a character set was compiled, this information - will get lost and overwritten in add_compiled_collation(). - */ - CHARSET_INFO *dst= all_charsets[cs->number]; - dst->number= cs->number; - if (cs->comment) - if (!(dst->comment= my_once_strdup(cs->comment,MYF(MY_WME)))) - return MY_XML_ERROR; - if (cs->csname) - if (!(dst->csname= my_once_strdup(cs->csname,MYF(MY_WME)))) - return MY_XML_ERROR; - if (cs->name) - if (!(dst->name= my_once_strdup(cs->name,MYF(MY_WME)))) - return MY_XML_ERROR; - } - cs->number= 0; - cs->primary_number= 0; - cs->binary_number= 0; - cs->name= NULL; - cs->state= 0; - cs->sort_order= NULL; - cs->state= 0; - } - return MY_XML_OK; -} - - -#define MY_MAX_ALLOWED_BUF 1024*1024 -#define MY_CHARSET_INDEX "Index.xml" - -const char *charsets_dir= NULL; - - -static my_bool my_read_charset_file(const char *filename, myf myflags) -{ - uchar *buf; - int fd; - size_t len, tmp_len; - MY_STAT stat_info; - - if (!my_stat(filename, &stat_info, MYF(myflags)) || - ((len= (uint)stat_info.st_size) > MY_MAX_ALLOWED_BUF) || - !(buf= (uchar*) my_malloc(len,myflags))) - return TRUE; - - if ((fd= mysql_file_open(key_file_charset, filename, O_RDONLY, myflags)) < 0) - goto error; - tmp_len= mysql_file_read(fd, buf, len, myflags); - mysql_file_close(fd, myflags); - if (tmp_len != len) - goto error; - - if (my_parse_charset_xml((char*) buf,len,add_collation)) - { -#ifdef NOT_YET - printf("ERROR at line %d pos %d '%s'\n", - my_xml_error_lineno(&p)+1, - my_xml_error_pos(&p), - my_xml_error_string(&p)); -#endif - } - - my_free(buf); - return FALSE; - -error: - my_free(buf); - return TRUE; -} - - -char *get_charsets_dir(char *buf) -{ - const char *sharedir= SHAREDIR; - char *res; - DBUG_ENTER("get_charsets_dir"); - - if (charsets_dir != NULL) - strmake(buf, charsets_dir, FN_REFLEN-1); - else - { - if (test_if_hard_path(sharedir) || - is_prefix(sharedir, DEFAULT_CHARSET_HOME)) - strxmov(buf, sharedir, "/", CHARSET_DIR, NullS); - else - strxmov(buf, DEFAULT_CHARSET_HOME, "/", sharedir, "/", CHARSET_DIR, - NullS); - } - res= convert_dirname(buf,buf,NullS); - DBUG_PRINT("info",("charsets dir: '%s'", buf)); - DBUG_RETURN(res); -} - -CHARSET_INFO *all_charsets[MY_ALL_CHARSETS_SIZE]={NULL}; -CHARSET_INFO *default_charset_info = &my_charset_latin1; - -void add_compiled_collation(CHARSET_INFO *cs) -{ - all_charsets[cs->number]= cs; - cs->state|= MY_CS_AVAILABLE; -} - -static void *cs_alloc(size_t size) -{ - return my_once_alloc(size, MYF(MY_WME)); -} - - -static my_pthread_once_t charsets_initialized= MY_PTHREAD_ONCE_INIT; -static my_pthread_once_t charsets_template= MY_PTHREAD_ONCE_INIT; - -static void init_available_charsets(void) -{ - char fname[FN_REFLEN + sizeof(MY_CHARSET_INDEX)]; - CHARSET_INFO **cs; - - bzero(&all_charsets,sizeof(all_charsets)); - init_compiled_charsets(MYF(0)); - - /* Copy compiled charsets */ - for (cs=all_charsets; - cs < all_charsets+array_elements(all_charsets)-1 ; - cs++) - { - if (*cs) - { - if (cs[0]->ctype) - if (init_state_maps(*cs)) - *cs= NULL; - } - } - - strmov(get_charsets_dir(fname), MY_CHARSET_INDEX); - my_read_charset_file(fname, MYF(0)); -} - - -void free_charsets(void) -{ - charsets_initialized= charsets_template; -} - - -static const char* -get_collation_name_alias(const char *name, char *buf, size_t bufsize) -{ - if (!strncasecmp(name, "utf8mb3_", 8)) - { - my_snprintf(buf, bufsize, "utf8_%s", name + 8); - return buf; - } - return NULL; -} - - -uint get_collation_number(const char *name) -{ - uint id; - char alias[64]; - my_pthread_once(&charsets_initialized, init_available_charsets); - if ((id= get_collation_number_internal(name))) - return id; - if ((name= get_collation_name_alias(name, alias, sizeof(alias)))) - return get_collation_number_internal(name); - return 0; -} - - -static uint -get_charset_number_internal(const char *charset_name, uint cs_flags) -{ - CHARSET_INFO **cs; - - for (cs= all_charsets; - cs < all_charsets + array_elements(all_charsets); - cs++) - { - if ( cs[0] && cs[0]->csname && (cs[0]->state & cs_flags) && - !my_strcasecmp(&my_charset_latin1, cs[0]->csname, charset_name)) - return cs[0]->number; - } - return 0; -} - - -static const char* -get_charset_name_alias(const char *name) -{ - if (!my_strcasecmp(&my_charset_latin1, name, "utf8mb3")) - return "utf8"; - return NULL; -} - - -uint get_charset_number(const char *charset_name, uint cs_flags) -{ - uint id; - my_pthread_once(&charsets_initialized, init_available_charsets); - if ((id= get_charset_number_internal(charset_name, cs_flags))) - return id; - if ((charset_name= get_charset_name_alias(charset_name))) - return get_charset_number_internal(charset_name, cs_flags); - return 0; -} - - -const char *get_charset_name(uint charset_number) -{ - CHARSET_INFO *cs; - my_pthread_once(&charsets_initialized, init_available_charsets); - - cs=all_charsets[charset_number]; - if (cs && (cs->number == charset_number) && cs->name ) - return (char*) cs->name; - - return (char*) "?"; /* this mimics find_type() */ -} - - -static CHARSET_INFO *get_internal_charset(uint cs_number, myf flags) -{ - char buf[FN_REFLEN]; - CHARSET_INFO *cs; - - if ((cs= all_charsets[cs_number])) - { - if (cs->state & MY_CS_READY) /* if CS is already initialized */ - return cs; - - /* - To make things thread safe we are not allowing other threads to interfere - while we may changing the cs_info_table - */ - mysql_mutex_lock(&THR_LOCK_charset); - - if (!(cs->state & (MY_CS_COMPILED|MY_CS_LOADED))) /* if CS is not in memory */ - { - strxmov(get_charsets_dir(buf), cs->csname, ".xml", NullS); - my_read_charset_file(buf,flags); - } - - if (cs->state & MY_CS_AVAILABLE) - { - if (!(cs->state & MY_CS_READY)) - { - if ((cs->cset->init && cs->cset->init(cs, cs_alloc)) || - (cs->coll->init && cs->coll->init(cs, cs_alloc))) - cs= NULL; - else - cs->state|= MY_CS_READY; - } - } - else - cs= NULL; - - mysql_mutex_unlock(&THR_LOCK_charset); - } - return cs; -} - - -CHARSET_INFO *get_charset(uint cs_number, myf flags) -{ - CHARSET_INFO *cs; - if (cs_number == default_charset_info->number) - return default_charset_info; - - my_pthread_once(&charsets_initialized, init_available_charsets); - - if (!cs_number || cs_number > array_elements(all_charsets)) - return NULL; - - cs=get_internal_charset(cs_number, flags); - - if (!cs && (flags & MY_WME)) - { - char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)], cs_string[23]; - strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX); - cs_string[0]='#'; - int10_to_str(cs_number, cs_string+1, 10); - my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_string, index_file); - } - return cs; -} - -CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags) -{ - uint cs_number; - CHARSET_INFO *cs; - my_pthread_once(&charsets_initialized, init_available_charsets); - - cs_number=get_collation_number(cs_name); - cs= cs_number ? get_internal_charset(cs_number,flags) : NULL; - - if (!cs && (flags & MY_WME)) - { - char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)]; - strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX); - my_error(EE_UNKNOWN_COLLATION, MYF(ME_BELL), cs_name, index_file); - } - - return cs; -} - - -CHARSET_INFO *get_charset_by_csname(const char *cs_name, - uint cs_flags, - myf flags) -{ - uint cs_number; - CHARSET_INFO *cs; - DBUG_ENTER("get_charset_by_csname"); - DBUG_PRINT("enter",("name: '%s'", cs_name)); - - my_pthread_once(&charsets_initialized, init_available_charsets); - - cs_number= get_charset_number(cs_name, cs_flags); - cs= cs_number ? get_internal_charset(cs_number, flags) : NULL; - - if (!cs && (flags & MY_WME)) - { - char index_file[FN_REFLEN + sizeof(MY_CHARSET_INDEX)]; - strmov(get_charsets_dir(index_file),MY_CHARSET_INDEX); - my_error(EE_UNKNOWN_CHARSET, MYF(ME_BELL), cs_name, index_file); - } - - DBUG_RETURN(cs); -} - - -/** - Resolve character set by the character set name (utf8, latin1, ...). - - The function tries to resolve character set by the specified name. If - there is character set with the given name, it is assigned to the "cs" - parameter and FALSE is returned. If there is no such character set, - "default_cs" is assigned to the "cs" and TRUE is returned. - - @param[in] cs_name Character set name. - @param[in] default_cs Default character set. - @param[out] cs Variable to store character set. - - @return FALSE if character set was resolved successfully; TRUE if there - is no character set with given name. -*/ - -my_bool resolve_charset(const char *cs_name, - CHARSET_INFO *default_cs, - CHARSET_INFO **cs) -{ - *cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0)); - - if (*cs == NULL) - { - *cs= default_cs; - return TRUE; - } - - return FALSE; -} - - -/** - Resolve collation by the collation name (utf8_general_ci, ...). - - The function tries to resolve collation by the specified name. If there - is collation with the given name, it is assigned to the "cl" parameter - and FALSE is returned. If there is no such collation, "default_cl" is - assigned to the "cl" and TRUE is returned. - - @param[out] cl Variable to store collation. - @param[in] cl_name Collation name. - @param[in] default_cl Default collation. - - @return FALSE if collation was resolved successfully; TRUE if there is no - collation with given name. -*/ - -my_bool resolve_collation(const char *cl_name, - CHARSET_INFO *default_cl, - CHARSET_INFO **cl) -{ - *cl= get_charset_by_name(cl_name, MYF(0)); - - if (*cl == NULL) - { - *cl= default_cl; - return TRUE; - } - - return FALSE; -} - - -/* - Escape string with backslashes (\) - - SYNOPSIS - escape_string_for_mysql() - charset_info Charset of the strings - to Buffer for escaped string - to_length Length of destination buffer, or 0 - from The string to escape - length The length of the string to escape - - DESCRIPTION - This escapes the contents of a string by adding backslashes before special - characters, and turning others into specific escape sequences, such as - turning newlines into \n and null bytes into \0. - - NOTE - To maintain compatibility with the old C API, to_length may be 0 to mean - "big enough" - - RETURN VALUES - (size_t) -1 The escaped string did not fit in the to buffer - # The length of the escaped string -*/ - -size_t escape_string_for_mysql(CHARSET_INFO *charset_info, - char *to, size_t to_length, - const char *from, size_t length) -{ - const char *to_start= to; - const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); - my_bool overflow= FALSE; -#ifdef USE_MB - my_bool use_mb_flag= use_mb(charset_info); -#endif - for (end= from + length; from < end; from++) - { - char escape= 0; -#ifdef USE_MB - int tmp_length; - if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) - { - if (to + tmp_length > to_end) - { - overflow= TRUE; - break; - } - while (tmp_length--) - *to++= *from++; - from--; - continue; - } - /* - If the next character appears to begin a multi-byte character, we - escape that first byte of that apparent multi-byte character. (The - character just looks like a multi-byte character -- if it were actually - a multi-byte character, it would have been passed through in the test - above.) - - Without this check, we can create a problem by converting an invalid - multi-byte character into a valid one. For example, 0xbf27 is not - a valid GBK character, but 0xbf5c is. (0x27 = ', 0x5c = \) - */ - if (use_mb_flag && (tmp_length= my_mbcharlen(charset_info, *from)) > 1) - escape= *from; - else -#endif - switch (*from) { - case 0: /* Must be escaped for 'mysql' */ - escape= '0'; - break; - case '\n': /* Must be escaped for logs */ - escape= 'n'; - break; - case '\r': - escape= 'r'; - break; - case '\\': - escape= '\\'; - break; - case '\'': - escape= '\''; - break; - case '"': /* Better safe than sorry */ - escape= '"'; - break; - case '\032': /* This gives problems on Win32 */ - escape= 'Z'; - break; - } - if (escape) - { - if (to + 2 > to_end) - { - overflow= TRUE; - break; - } - *to++= '\\'; - *to++= escape; - } - else - { - if (to + 1 > to_end) - { - overflow= TRUE; - break; - } - *to++= *from; - } - } - *to= 0; - return overflow ? (size_t) -1 : (size_t) (to - to_start); -} - - -#ifdef BACKSLASH_MBTAIL -static CHARSET_INFO *fs_cset_cache= NULL; - -CHARSET_INFO *fs_character_set() -{ - if (!fs_cset_cache) - { - char buf[10]= "cp"; - GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_IDEFAULTANSICODEPAGE, - buf+2, sizeof(buf)-3); - /* - We cannot call get_charset_by_name here - because fs_character_set() is executed before - LOCK_THD_charset mutex initialization, which - is used inside get_charset_by_name. - As we're now interested in cp932 only, - let's just detect it using strcmp(). - */ - fs_cset_cache= !strcmp(buf, "cp932") ? - &my_charset_cp932_japanese_ci : &my_charset_bin; - } - return fs_cset_cache; -} -#endif - -/* - Escape apostrophes by doubling them up - - SYNOPSIS - escape_quotes_for_mysql() - charset_info Charset of the strings - to Buffer for escaped string - to_length Length of destination buffer, or 0 - from The string to escape - length The length of the string to escape - - DESCRIPTION - This escapes the contents of a string by doubling up any apostrophes that - it contains. This is used when the NO_BACKSLASH_ESCAPES SQL_MODE is in - effect on the server. - - NOTE - To be consistent with escape_string_for_mysql(), to_length may be 0 to - mean "big enough" - - RETURN VALUES - ~0 The escaped string did not fit in the to buffer - >=0 The length of the escaped string -*/ - -size_t escape_quotes_for_mysql(CHARSET_INFO *charset_info, - char *to, size_t to_length, - const char *from, size_t length) -{ - const char *to_start= to; - const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length); - my_bool overflow= FALSE; -#ifdef USE_MB - my_bool use_mb_flag= use_mb(charset_info); -#endif - for (end= from + length; from < end; from++) - { -#ifdef USE_MB - int tmp_length; - if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end))) - { - if (to + tmp_length > to_end) - { - overflow= TRUE; - break; - } - while (tmp_length--) - *to++= *from++; - from--; - continue; - } - /* - We don't have the same issue here with a non-multi-byte character being - turned into a multi-byte character by the addition of an escaping - character, because we are only escaping the ' character with itself. - */ -#endif - if (*from == '\'') - { - if (to + 2 > to_end) - { - overflow= TRUE; - break; - } - *to++= '\''; - *to++= '\''; - } - else - { - if (to + 1 > to_end) - { - overflow= TRUE; - break; - } - *to++= *from; - } - } - *to= 0; - return overflow ? (ulong)~0 : (ulong) (to - to_start); -} diff --git a/dep/mysqllite/mysys/checksum.c b/dep/mysqllite/mysys/checksum.c deleted file mode 100644 index a96ea31ea0e..00000000000 --- a/dep/mysqllite/mysys/checksum.c +++ /dev/null @@ -1,35 +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 <my_global.h> -#include <my_sys.h> -#include <zlib.h> - -/* - Calculate a long checksum for a memoryblock. - - SYNOPSIS - my_checksum() - crc start value for crc - pos pointer to memory block - length length of the block -*/ - -ha_checksum my_checksum(ha_checksum crc, const uchar *pos, size_t length) -{ - return (ha_checksum)crc32((uint)crc, pos, (uint)length); -} - diff --git a/dep/mysqllite/mysys/default.c b/dep/mysqllite/mysys/default.c deleted file mode 100644 index 75eb4709e1e..00000000000 --- a/dep/mysqllite/mysys/default.c +++ /dev/null @@ -1,1217 +0,0 @@ -/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/**************************************************************************** - Add all options from files named "group".cnf from the default_directories - before the command line arguments. - On Windows defaults will also search in the Windows directory for a file - called 'group'.ini - As long as the program uses the last argument for conflicting - options one only have to add a call to "load_defaults" to enable - use of default values. - pre- and end 'blank space' are removed from options and values. The - following escape sequences are recognized in values: \b \t \n \r \\ - - The following arguments are handled automaticly; If used, they must be - first argument on the command line! - --no-defaults ; no options are read. - --defaults-file=full-path-to-default-file ; Only this file will be read. - --defaults-extra-file=full-path-to-default-file ; Read this file before ~/ - --defaults-group-suffix ; Also read groups with concat(group, suffix) - --print-defaults ; Print the modified command line and exit -****************************************************************************/ - -#include "mysys_priv.h" -#include "m_string.h" -#include "m_ctype.h" -#include <my_dir.h> -#ifdef __WIN__ -#include <winbase.h> -#endif - -/** - arguments separator - - load_defaults() loads arguments from config file and put them - before the arguments from command line, this separator is used to - separate the arguments loaded from config file and arguments user - provided on command line. - - Options with value loaded from config file are always in the form - '--option=value', while for command line options, the value can be - given as the next argument. Thus we used a separator so that - handle_options() can distinguish them. - - Note: any other places that does not need to distinguish them - should skip the separator. - - The content of arguments separator does not matter, one should only - check the pointer, use "----args-separator----" here to ease debug - if someone misused it. - - See BUG#25192 -*/ -const char *args_separator= "----args-separator----"; -const char *my_defaults_file=0; -const char *my_defaults_group_suffix=0; -const char *my_defaults_extra_file=0; - -static char my_defaults_file_buffer[FN_REFLEN]; -static char my_defaults_extra_file_buffer[FN_REFLEN]; - -static my_bool defaults_already_read= FALSE; - -/* Which directories are searched for options (and in which order) */ - -#define MAX_DEFAULT_DIRS 6 -#define DEFAULT_DIRS_SIZE (MAX_DEFAULT_DIRS + 1) /* Terminate with NULL */ -static const char **default_directories = NULL; - -#ifdef __WIN__ -static const char *f_extensions[]= { ".ini", ".cnf", 0 }; -#define NEWLINE "\r\n" -#else -static const char *f_extensions[]= { ".cnf", 0 }; -#define NEWLINE "\n" -#endif - -static int handle_default_option(void *in_ctx, const char *group_name, - const char *option); - -/* - This structure defines the context that we pass to callback - function 'handle_default_option' used in search_default_file - to process each option. This context is used if search_default_file - was called from load_defaults. -*/ - -struct handle_option_ctx -{ - MEM_ROOT *alloc; - DYNAMIC_ARRAY *args; - TYPELIB *group; -}; - -static int search_default_file(Process_option_func func, void *func_ctx, - const char *dir, const char *config_file); -static int search_default_file_with_ext(Process_option_func func, - void *func_ctx, - const char *dir, const char *ext, - const char *config_file, int recursion_level); - - -/** - Create the list of default directories. - - @param alloc MEM_ROOT where the list of directories is stored - - @details - The directories searched, in order, are: - - Windows: GetSystemWindowsDirectory() - - Windows: GetWindowsDirectory() - - Windows: C:/ - - Windows: Directory above where the executable is located - - Unix: /etc/ - - Unix: /etc/mysql/ - - Unix: --sysconfdir=<path> (compile-time option) - - ALL: getenv(DEFAULT_HOME_ENV) - - ALL: --defaults-extra-file=<path> (run-time option) - - Unix: ~/ - - On all systems, if a directory is already in the list, it will be moved - to the end of the list. This avoids reading defaults files multiple times, - while ensuring the correct precedence. - - @retval NULL Failure (out of memory, probably) - @retval other Pointer to NULL-terminated array of default directories -*/ - -static const char **init_default_directories(MEM_ROOT *alloc); - - -static char *remove_end_comment(char *ptr); - - -/* - Expand a file name so that the current working directory is added if - the name is relative. - - RETURNS - 0 All OK - 2 Out of memory or path to long - 3 Not able to get working directory - */ - -static int -fn_expand(const char *filename, char *result_buf) -{ - char dir[FN_REFLEN]; - const int flags= MY_UNPACK_FILENAME | MY_SAFE_PATH | MY_RELATIVE_PATH; - DBUG_ENTER("fn_expand"); - DBUG_PRINT("enter", ("filename: %s, result_buf: 0x%lx", - filename, (unsigned long) result_buf)); - if (my_getwd(dir, sizeof(dir), MYF(0))) - DBUG_RETURN(3); - DBUG_PRINT("debug", ("dir: %s", dir)); - if (fn_format(result_buf, filename, dir, NULL, flags) == NULL) - DBUG_RETURN(2); - DBUG_PRINT("return", ("result: %s", result_buf)); - DBUG_RETURN(0); -} - -/* - Process config files in default directories. - - SYNOPSIS - my_search_option_files() - conf_file Basename for configuration file to search for. - If this is a path, then only this file is read. - argc Pointer to argc of original program - argv Pointer to argv of original program - args_used Pointer to variable for storing the number of - arguments used. - func Pointer to the function to process options - func_ctx It's context. Usually it is the structure to - store additional options. - DESCRIPTION - Process the default options from argc & argv - Read through each found config file looks and calls 'func' to process - each option. - - NOTES - --defaults-group-suffix is only processed if we are called from - load_defaults(). - - - RETURN - 0 ok - 1 given cinf_file doesn't exist - 2 out of memory - 3 Can't get current working directory - - The global variable 'my_defaults_group_suffix' is updated with value for - --defaults_group_suffix -*/ - -int my_search_option_files(const char *conf_file, int *argc, char ***argv, - uint *args_used, Process_option_func func, - void *func_ctx, const char **default_directories) -{ - const char **dirs, *forced_default_file, *forced_extra_defaults; - int error= 0; - DBUG_ENTER("my_search_option_files"); - - /* Check if we want to force the use a specific default file */ - *args_used+= get_defaults_options(*argc - *args_used, *argv + *args_used, - (char **) &forced_default_file, - (char **) &forced_extra_defaults, - (char **) &my_defaults_group_suffix); - - if (! my_defaults_group_suffix) - my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV)); - - if (forced_extra_defaults && !defaults_already_read) - { - int error= fn_expand(forced_extra_defaults, my_defaults_extra_file_buffer); - if (error) - DBUG_RETURN(error); - my_defaults_extra_file= my_defaults_extra_file_buffer; - } - - if (forced_default_file && !defaults_already_read) - { - int error= fn_expand(forced_default_file, my_defaults_file_buffer); - if (error) - DBUG_RETURN(error); - my_defaults_file= my_defaults_file_buffer; - } - - defaults_already_read= TRUE; - - /* - We can only handle 'defaults-group-suffix' if we are called from - load_defaults() as otherwise we can't know the type of 'func_ctx' - */ - - if (my_defaults_group_suffix && func == handle_default_option) - { - /* Handle --defaults-group-suffix= */ - uint i; - const char **extra_groups; - const size_t instance_len= strlen(my_defaults_group_suffix); - struct handle_option_ctx *ctx= (struct handle_option_ctx*) func_ctx; - char *ptr; - TYPELIB *group= ctx->group; - - if (!(extra_groups= - (const char**)alloc_root(ctx->alloc, - (2*group->count+1)*sizeof(char*)))) - DBUG_RETURN(2); - - for (i= 0; i < group->count; i++) - { - size_t len; - extra_groups[i]= group->type_names[i]; /** copy group */ - - len= strlen(extra_groups[i]); - if (!(ptr= alloc_root(ctx->alloc, (uint) (len+instance_len+1)))) - DBUG_RETURN(2); - - extra_groups[i+group->count]= ptr; - - /** Construct new group */ - memcpy(ptr, extra_groups[i], len); - memcpy(ptr+len, my_defaults_group_suffix, instance_len+1); - } - - group->count*= 2; - group->type_names= extra_groups; - group->type_names[group->count]= 0; - } - - if (my_defaults_file) - { - if ((error= search_default_file_with_ext(func, func_ctx, "", "", - my_defaults_file, 0)) < 0) - goto err; - if (error > 0) - { - fprintf(stderr, "Could not open required defaults file: %s\n", - my_defaults_file); - goto err; - } - } - else if (dirname_length(conf_file)) - { - if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0) - goto err; - } - else - { - for (dirs= default_directories ; *dirs; dirs++) - { - if (**dirs) - { - if (search_default_file(func, func_ctx, *dirs, conf_file) < 0) - goto err; - } - else if (my_defaults_extra_file) - { - if ((error= search_default_file_with_ext(func, func_ctx, "", "", - my_defaults_extra_file, 0)) < 0) - goto err; /* Fatal error */ - if (error > 0) - { - fprintf(stderr, "Could not open required defaults file: %s\n", - my_defaults_extra_file); - goto err; - } - } - } - } - - DBUG_RETURN(0); - -err: - fprintf(stderr,"Fatal error in defaults handling. Program aborted\n"); - DBUG_RETURN(1); -} - - -/* - The option handler for load_defaults. - - SYNOPSIS - handle_deault_option() - in_ctx Handler context. In this case it is a - 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). 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 - to the array if yes. Some other handler can record, for instance, all - groups and their options, not knowing in advance the names and amount of - groups. - - RETURN - 0 - ok - 1 - error occured -*/ - -static int handle_default_option(void *in_ctx, const char *group_name, - const char *option) -{ - 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, strlen(option) + 1))) - return 1; - if (insert_dynamic(ctx->args, (uchar*) &tmp)) - return 1; - strmov(tmp, option); - } - - return 0; -} - - -/* - Gets options from the command line - - SYNOPSIS - get_defaults_options() - argc Pointer to argc of original program - argv Pointer to argv of original program - defaults --defaults-file option - extra_defaults --defaults-extra-file option - - RETURN - # Number of arguments used from *argv - defaults and extra_defaults will be set to option of the appropriate - items of argv array, or to NULL if there are no such options -*/ - -int get_defaults_options(int argc, char **argv, - char **defaults, - char **extra_defaults, - char **group_suffix) -{ - int org_argc= argc, prev_argc= 0; - *defaults= *extra_defaults= *group_suffix= 0; - - while (argc >= 2 && argc != prev_argc) - { - /* Skip program name or previously handled argument */ - argv++; - prev_argc= argc; /* To check if we found */ - if (!*defaults && is_prefix(*argv,"--defaults-file=")) - { - *defaults= *argv + sizeof("--defaults-file=")-1; - argc--; - continue; - } - if (!*extra_defaults && is_prefix(*argv,"--defaults-extra-file=")) - { - *extra_defaults= *argv + sizeof("--defaults-extra-file=")-1; - argc--; - continue; - } - if (!*group_suffix && is_prefix(*argv, "--defaults-group-suffix=")) - { - *group_suffix= *argv + sizeof("--defaults-group-suffix=")-1; - argc--; - continue; - } - } - return org_argc - argc; -} - -/* - Wrapper around my_load_defaults() for interface compatibility. - - SYNOPSIS - load_defaults() - conf_file Basename for configuration file to search for. - If this is a path, then only this file is read. - groups Which [group] entrys to read. - Points to an null terminated array of pointers - argc Pointer to argc of original program - argv Pointer to argv of original program - - NOTES - - This function is NOT thread-safe as it uses a global pointer internally. - See also notes for my_load_defaults(). - - RETURN - 0 ok - 1 The given conf_file didn't exists -*/ -int load_defaults(const char *conf_file, const char **groups, - int *argc, char ***argv) -{ - return my_load_defaults(conf_file, groups, argc, argv, &default_directories); -} - -/* - Read options from configurations files - - SYNOPSIS - my_load_defaults() - conf_file Basename for configuration file to search for. - If this is a path, then only this file is read. - groups Which [group] entrys to read. - Points to an null terminated array of pointers - argc Pointer to argc of original program - argv Pointer to argv of original program - default_directories Pointer to a location where a pointer to the list - of default directories will be stored - - IMPLEMENTATION - - Read options from configuration files and put them BEFORE the arguments - that are already in argc and argv. This way the calling program can - easily command line options override options in configuration files - - NOTES - In case of fatal error, the function will print a warning and do - exit(1) - - To free used memory one should call free_defaults() with the argument - that was put in *argv - - RETURN - - If successful, 0 is returned. If 'default_directories' is not NULL, - a pointer to the array of default directory paths is stored to a location - it points to. That stored value must be passed to my_search_option_files() - later. - - - 1 is returned if the given conf_file didn't exist. In this case, the - value pointed to by default_directories is undefined. -*/ - - -int my_load_defaults(const char *conf_file, const char **groups, - int *argc, char ***argv, const char ***default_directories) -{ - DYNAMIC_ARRAY args; - TYPELIB group; - my_bool found_print_defaults= 0; - uint args_used= 0; - int error= 0; - MEM_ROOT alloc; - char *ptr,**res; - struct handle_option_ctx ctx; - const char **dirs; - DBUG_ENTER("load_defaults"); - - init_alloc_root(&alloc,512,0); - if ((dirs= init_default_directories(&alloc)) == NULL) - goto err; - /* - Check if the user doesn't want any default option processing - --no-defaults is always the first option - */ - if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults")) - { - /* remove the --no-defaults argument and return only the other arguments */ - uint i; - if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ - (*argc + 1)*sizeof(char*)))) - goto err; - res= (char**) (ptr+sizeof(alloc)); - res[0]= **argv; /* Copy program name */ - /* set arguments separator */ - res[1]= (char *)args_separator; - for (i=2 ; i < (uint) *argc ; i++) - res[i]=argv[0][i]; - res[i]=0; /* End pointer */ - *argv=res; - *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ - if (default_directories) - *default_directories= dirs; - DBUG_RETURN(0); - } - - group.count=0; - group.name= "defaults"; - group.type_names= groups; - - for (; *groups ; groups++) - group.count++; - - if (my_init_dynamic_array(&args, sizeof(char*),*argc, 32)) - goto err; - - ctx.alloc= &alloc; - ctx.args= &args; - ctx.group= &group; - - if ((error= my_search_option_files(conf_file, argc, argv, &args_used, - handle_default_option, (void *) &ctx, - dirs))) - { - free_root(&alloc,MYF(0)); - DBUG_RETURN(error); - } - /* - Here error contains <> 0 only if we have a fully specified conf_file - or a forced default file - */ - if (!(ptr=(char*) alloc_root(&alloc,sizeof(alloc)+ - (args.elements + *argc + 1 + 1) *sizeof(char*)))) - goto err; - res= (char**) (ptr+sizeof(alloc)); - - /* copy name + found arguments + command line arguments to new array */ - res[0]= argv[0][0]; /* Name MUST be set, even by embedded library */ - memcpy((uchar*) (res+1), args.buffer, args.elements*sizeof(char*)); - /* Skip --defaults-xxx options */ - (*argc)-= args_used; - (*argv)+= args_used; - - /* - Check if we wan't to see the new argument list - This options must always be the last of the default options - */ - if (*argc >= 2 && !strcmp(argv[0][1],"--print-defaults")) - { - found_print_defaults=1; - --*argc; ++*argv; /* skip argument */ - } - - /* set arguments separator for arguments from config file and - command line */ - res[args.elements+1]= (char *)args_separator; - - if (*argc) - memcpy((uchar*) (res+1+args.elements+1), (char*) ((*argv)+1), - (*argc-1)*sizeof(char*)); - res[args.elements+ *argc+1]=0; /* last null */ - - (*argc)+=args.elements+1; - *argv= (char**) res; - *(MEM_ROOT*) ptr= alloc; /* Save alloc root for free */ - delete_dynamic(&args); - if (found_print_defaults) - { - int i; - printf("%s would have been started with the following arguments:\n", - **argv); - for (i=1 ; i < *argc ; i++) - if ((*argv)[i] != args_separator) /* skip arguments separator */ - printf("%s ", (*argv)[i]); - puts(""); - exit(0); - } - - if (default_directories) - *default_directories= dirs; - - DBUG_RETURN(0); - - err: - fprintf(stderr,"Fatal error in defaults handling. Program aborted\n"); - exit(1); - return 0; /* Keep compiler happy */ -} - - -void free_defaults(char **argv) -{ - MEM_ROOT ptr; - memcpy(&ptr, ((char *) argv) - sizeof(ptr), sizeof(ptr)); - free_root(&ptr,MYF(0)); -} - - -static int search_default_file(Process_option_func opt_handler, - void *handler_ctx, - const char *dir, - const char *config_file) -{ - char **ext; - const char *empty_list[]= { "", 0 }; - my_bool have_ext= fn_ext(config_file)[0] != 0; - const char **exts_to_use= have_ext ? empty_list : f_extensions; - - for (ext= (char**) exts_to_use; *ext; ext++) - { - int error; - if ((error= search_default_file_with_ext(opt_handler, handler_ctx, - dir, *ext, - config_file, 0)) < 0) - return error; - } - return 0; -} - - -/* - Skip over keyword and get argument after keyword - - SYNOPSIS - get_argument() - keyword Include directive keyword - kwlen Length of keyword - ptr Pointer to the keword in the line under process - line line number - - RETURN - 0 error - # Returns pointer to the argument after the keyword. -*/ - -static char *get_argument(const char *keyword, size_t kwlen, - char *ptr, char *name, uint line) -{ - char *end; - - /* Skip over "include / includedir keyword" and following whitespace */ - - for (ptr+= kwlen - 1; - my_isspace(&my_charset_latin1, ptr[0]); - ptr++) - {} - - /* - Trim trailing whitespace from directory name - The -1 below is for the newline added by fgets() - Note that my_isspace() is true for \r and \n - */ - for (end= ptr + strlen(ptr) - 1; - my_isspace(&my_charset_latin1, *(end - 1)); - end--) - {} - end[0]= 0; /* Cut off end space */ - - /* Print error msg if there is nothing after !include* directive */ - if (end <= ptr) - { - fprintf(stderr, - "error: Wrong '!%s' directive in config file: %s at line %d\n", - keyword, name, line); - return 0; - } - return ptr; -} - - -/* - Open a configuration file (if exists) and read given options from it - - SYNOPSIS - search_default_file_with_ext() - opt_handler Option handler function. It is used to process - every separate option. - handler_ctx Pointer to the structure to store actual - parameters of the function. - dir directory to read - ext Extension for configuration file - config_file Name of configuration file - group groups to read - recursion_level the level of recursion, got while processing - "!include" or "!includedir" - - RETURN - 0 Success - -1 Fatal error, abort - 1 File not found (Warning) -*/ - -static int search_default_file_with_ext(Process_option_func opt_handler, - void *handler_ctx, - const char *dir, - const char *ext, - const char *config_file, - int recursion_level) -{ - char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext; - char *value, option[4096+2], tmp[FN_REFLEN]; - static const char includedir_keyword[]= "includedir"; - static const char include_keyword[]= "include"; - const int max_recursion_level= 10; - MYSQL_FILE *fp; - uint line=0; - my_bool found_group=0; - uint i; - MY_DIR *search_dir; - FILEINFO *search_file; - - if ((dir ? strlen(dir) : 0 )+strlen(config_file) >= FN_REFLEN-3) - return 0; /* Ignore wrong paths */ - if (dir) - { - end=convert_dirname(name, dir, NullS); - if (dir[0] == FN_HOMELIB) /* Add . to filenames in home */ - *end++='.'; - strxmov(end,config_file,ext,NullS); - } - else - { - strmov(name,config_file); - } - fn_format(name,name,"","",4); -#if !defined(__WIN__) - { - MY_STAT stat_info; - if (!my_stat(name,&stat_info,MYF(0))) - return 1; - /* - Ignore world-writable regular files. - This is mainly done to protect us to not read a file created by - the mysqld server, but the check is still valid in most context. - */ - if ((stat_info.st_mode & S_IWOTH) && - (stat_info.st_mode & S_IFMT) == S_IFREG) - { - fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n", - name); - return 0; - } - } -#endif - if (!(fp= mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0)))) - return 1; /* Ignore wrong files */ - - while (mysql_file_fgets(buff, sizeof(buff) - 1, fp)) - { - line++; - /* Ignore comment and empty lines */ - for (ptr= buff; my_isspace(&my_charset_latin1, *ptr); ptr++) - {} - - if (*ptr == '#' || *ptr == ';' || !*ptr) - continue; - - /* Configuration File Directives */ - if ((*ptr == '!')) - { - if (recursion_level >= max_recursion_level) - { - for (end= ptr + strlen(ptr) - 1; - my_isspace(&my_charset_latin1, *(end - 1)); - end--) - {} - end[0]= 0; - fprintf(stderr, - "Warning: skipping '%s' directive as maximum include" - "recursion level was reached in file %s at line %d\n", - ptr, name, line); - continue; - } - - /* skip over `!' and following whitespace */ - for (++ptr; my_isspace(&my_charset_latin1, ptr[0]); ptr++) - {} - - if ((!strncmp(ptr, includedir_keyword, - sizeof(includedir_keyword) - 1)) && - my_isspace(&my_charset_latin1, ptr[sizeof(includedir_keyword) - 1])) - { - if (!(ptr= get_argument(includedir_keyword, - sizeof(includedir_keyword), - ptr, name, line))) - goto err; - - if (!(search_dir= my_dir(ptr, MYF(MY_WME)))) - goto err; - - for (i= 0; i < (uint) search_dir->number_off_files; i++) - { - search_file= search_dir->dir_entry + i; - ext= fn_ext(search_file->name); - - /* check extension */ - for (tmp_ext= (char**) f_extensions; *tmp_ext; tmp_ext++) - { - if (!strcmp(ext, *tmp_ext)) - break; - } - - if (*tmp_ext) - { - fn_format(tmp, search_file->name, ptr, "", - MY_UNPACK_FILENAME | MY_SAFE_PATH); - - search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp, - recursion_level + 1); - } - } - - my_dirend(search_dir); - } - else if ((!strncmp(ptr, include_keyword, sizeof(include_keyword) - 1)) && - my_isspace(&my_charset_latin1, ptr[sizeof(include_keyword)-1])) - { - if (!(ptr= get_argument(include_keyword, - sizeof(include_keyword), ptr, - name, line))) - goto err; - - search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr, - recursion_level + 1); - } - - continue; - } - - if (*ptr == '[') /* Group name */ - { - found_group=1; - if (!(end=(char *) strchr(++ptr,']'))) - { - fprintf(stderr, - "error: Wrong group definition in config file: %s at line %d\n", - name,line); - goto err; - } - /* Remove end space */ - for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ; - end[0]=0; - - strmake(curr_gr, ptr, min((size_t) (end-ptr)+1, sizeof(curr_gr)-1)); - - /* signal that a new group is found */ - opt_handler(handler_ctx, curr_gr, NULL); - - continue; - } - if (!found_group) - { - fprintf(stderr, - "error: Found option without preceding group in config file: %s at line: %d\n", - name,line); - goto err; - } - - - end= remove_end_comment(ptr); - if ((value= strchr(ptr, '='))) - end= value; /* Option without argument */ - for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ; - if (!value) - { - strmake(strmov(option,"--"),ptr, (size_t) (end-ptr)); - if (opt_handler(handler_ctx, curr_gr, option)) - goto err; - } - else - { - /* Remove pre- and end space */ - char *value_end; - for (value++ ; my_isspace(&my_charset_latin1,*value); value++) ; - value_end=strend(value); - /* - We don't have to test for value_end >= value as we know there is - an '=' before - */ - for ( ; my_isspace(&my_charset_latin1,value_end[-1]) ; value_end--) ; - if (value_end < value) /* Empty string */ - value_end=value; - - /* remove quotes around argument */ - if ((*value == '\"' || *value == '\'') && /* First char is quote */ - (value + 1 < value_end ) && /* String is longer than 1 */ - *value == value_end[-1] ) /* First char is equal to last char */ - { - value++; - value_end--; - } - ptr=strnmov(strmov(option,"--"),ptr,(size_t) (end-ptr)); - *ptr++= '='; - - for ( ; value != value_end; value++) - { - if (*value == '\\' && value != value_end-1) - { - switch(*++value) { - case 'n': - *ptr++='\n'; - break; - case 't': - *ptr++= '\t'; - break; - case 'r': - *ptr++ = '\r'; - break; - case 'b': - *ptr++ = '\b'; - break; - case 's': - *ptr++= ' '; /* space */ - break; - case '\"': - *ptr++= '\"'; - break; - case '\'': - *ptr++= '\''; - break; - case '\\': - *ptr++= '\\'; - break; - default: /* Unknown; Keep '\' */ - *ptr++= '\\'; - *ptr++= *value; - break; - } - } - else - *ptr++= *value; - } - *ptr=0; - if (opt_handler(handler_ctx, curr_gr, option)) - goto err; - } - } - mysql_file_fclose(fp, MYF(0)); - return(0); - - err: - mysql_file_fclose(fp, MYF(0)); - return -1; /* Fatal error */ -} - - -static char *remove_end_comment(char *ptr) -{ - char quote= 0; /* we are inside quote marks */ - char escape= 0; /* symbol is protected by escape chagacter */ - - for (; *ptr; ptr++) - { - if ((*ptr == '\'' || *ptr == '\"') && !escape) - { - if (!quote) - quote= *ptr; - else if (quote == *ptr) - quote= 0; - } - /* We are not inside a string */ - if (!quote && *ptr == '#') - { - *ptr= 0; - return ptr; - } - escape= (quote && *ptr == '\\' && !escape); - } - return ptr; -} - - -void my_print_default_files(const char *conf_file) -{ - const char *empty_list[]= { "", 0 }; - my_bool have_ext= fn_ext(conf_file)[0] != 0; - const char **exts_to_use= have_ext ? empty_list : f_extensions; - char name[FN_REFLEN], **ext; - - puts("\nDefault options are read from the following files in the given order:"); - - if (dirname_length(conf_file)) - fputs(conf_file,stdout); - else - { - const char **dirs; - MEM_ROOT alloc; - init_alloc_root(&alloc,512,0); - - if ((dirs= init_default_directories(&alloc)) == NULL) - { - fputs("Internal error initializing default directories list", stdout); - } - else - { - for ( ; *dirs; dirs++) - { - for (ext= (char**) exts_to_use; *ext; ext++) - { - const char *pos; - char *end; - if (**dirs) - pos= *dirs; - else if (my_defaults_extra_file) - pos= my_defaults_extra_file; - else - continue; - end= convert_dirname(name, pos, NullS); - if (name[0] == FN_HOMELIB) /* Add . to filenames in home */ - *end++= '.'; - strxmov(end, conf_file, *ext, " ", NullS); - fputs(name, stdout); - } - } - } - - free_root(&alloc, MYF(0)); - } - puts(""); -} - -void print_defaults(const char *conf_file, const char **groups) -{ - const char **groups_save= groups; - my_print_default_files(conf_file); - - fputs("The following groups are read:",stdout); - for ( ; *groups ; groups++) - { - fputc(' ',stdout); - fputs(*groups,stdout); - } - - if (my_defaults_group_suffix) - { - groups= groups_save; - for ( ; *groups ; groups++) - { - fputc(' ',stdout); - fputs(*groups,stdout); - fputs(my_defaults_group_suffix,stdout); - } - } - puts("\nThe following options may be given as the first argument:\n\ ---print-defaults Print the program argument list and exit.\n\ ---no-defaults Don't read default options from any option file.\n\ ---defaults-file=# Only read default options from the given file #.\n\ ---defaults-extra-file=# Read this file after the global files are read."); -} - - -static int add_directory(MEM_ROOT *alloc, const char *dir, const char **dirs) -{ - char buf[FN_REFLEN]; - size_t len; - char *p; - my_bool err __attribute__((unused)); - - len= normalize_dirname(buf, dir); - if (!(p= strmake_root(alloc, buf, len))) - return 1; /* Failure */ - /* Should never fail if DEFAULT_DIRS_SIZE is correct size */ - err= array_append_string_unique(p, dirs, DEFAULT_DIRS_SIZE); - DBUG_ASSERT(err == FALSE); - - return 0; -} - - -#ifdef __WIN__ -/* - This wrapper for GetSystemWindowsDirectory() will dynamically bind to the - function if it is available, emulate it on NT4 Terminal Server by stripping - the \SYSTEM32 from the end of the results of GetSystemDirectory(), or just - return GetSystemDirectory(). - */ - -typedef UINT (WINAPI *GET_SYSTEM_WINDOWS_DIRECTORY)(LPSTR, UINT); - -static size_t my_get_system_windows_directory(char *buffer, size_t size) -{ - size_t count; - GET_SYSTEM_WINDOWS_DIRECTORY - func_ptr= (GET_SYSTEM_WINDOWS_DIRECTORY) - GetProcAddress(GetModuleHandle("kernel32.dll"), - "GetSystemWindowsDirectoryA"); - - if (func_ptr) - return func_ptr(buffer, (uint) size); - - /* - Windows NT 4.0 Terminal Server Edition: - To retrieve the shared Windows directory, call GetSystemDirectory and - trim the "System32" element from the end of the returned path. - */ - count= GetSystemDirectory(buffer, (uint) size); - if (count > 8 && stricmp(buffer+(count-8), "\\System32") == 0) - { - count-= 8; - buffer[count] = '\0'; - } - return count; -} - - -static const char *my_get_module_parent(char *buf, size_t size) -{ - char *last= NULL; - char *end; - if (!GetModuleFileName(NULL, buf, (DWORD) size)) - return NULL; - end= strend(buf); - - /* - Look for the second-to-last \ in the filename, but hang on - to a pointer after the last \ in case we're in the root of - a drive. - */ - for ( ; end > buf; end--) - { - if (*end == FN_LIBCHAR) - { - if (last) - { - /* Keep the last '\' as this works both with D:\ and a directory */ - end[1]= 0; - break; - } - last= end; - } - } - - return buf; -} -#endif /* __WIN__ */ - - -static const char **init_default_directories(MEM_ROOT *alloc) -{ - const char **dirs; - char *env; - int errors= 0; - - dirs= (const char **)alloc_root(alloc, DEFAULT_DIRS_SIZE * sizeof(char *)); - if (dirs == NULL) - return NULL; - bzero((char *) dirs, DEFAULT_DIRS_SIZE * sizeof(char *)); - -#ifdef __WIN__ - - { - char fname_buffer[FN_REFLEN]; - if (my_get_system_windows_directory(fname_buffer, sizeof(fname_buffer))) - errors += add_directory(alloc, fname_buffer, dirs); - - if (GetWindowsDirectory(fname_buffer, sizeof(fname_buffer))) - errors += add_directory(alloc, fname_buffer, dirs); - - errors += add_directory(alloc, "C:/", dirs); - - if (my_get_module_parent(fname_buffer, sizeof(fname_buffer)) != NULL) - errors += add_directory(alloc, fname_buffer, dirs); - } - -#else - - errors += add_directory(alloc, "/etc/", dirs); - errors += add_directory(alloc, "/etc/mysql/", dirs); - -#if defined(DEFAULT_SYSCONFDIR) - if (DEFAULT_SYSCONFDIR[0]) - errors += add_directory(alloc, DEFAULT_SYSCONFDIR, dirs); -#endif /* DEFAULT_SYSCONFDIR */ - -#endif - - if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) - errors += add_directory(alloc, env, dirs); - - /* Placeholder for --defaults-extra-file=<path> */ - errors += add_directory(alloc, "", dirs); - -#if !defined(__WIN__) - errors += add_directory(alloc, "~/", dirs); -#endif - - return (errors > 0 ? NULL : dirs); -} diff --git a/dep/mysqllite/mysys/errors.c b/dep/mysqllite/mysys/errors.c deleted file mode 100644 index c74ed292906..00000000000 --- a/dep/mysqllite/mysys/errors.c +++ /dev/null @@ -1,119 +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" - -#ifndef SHARED_LIBRARY - -const char *globerrs[GLOBERRS]= -{ - "Can't create/write to file '%s' (Errcode: %d)", - "Error reading file '%s' (Errcode: %d)", - "Error writing file '%s' (Errcode: %d)", - "Error on close of '%s' (Errcode: %d)", - "Out of memory (Needed %u bytes)", - "Error on delete of '%s' (Errcode: %d)", - "Error on rename of '%s' to '%s' (Errcode: %d)", - "", - "Unexpected eof found when reading file '%s' (Errcode: %d)", - "Can't lock file (Errcode: %d)", - "Can't unlock file (Errcode: %d)", - "Can't read dir of '%s' (Errcode: %d)", - "Can't get stat of '%s' (Errcode: %d)", - "Can't change size of file (Errcode: %d)", - "Can't open stream from handle (Errcode: %d)", - "Can't get working dirctory (Errcode: %d)", - "Can't change dir to '%s' (Errcode: %d)", - "Warning: '%s' had %d links", - "Warning: %d files and %d streams is left open\n", - "Disk is full writing '%s' (Errcode: %d). Waiting for someone to free space... (Expect up to %d secs delay for server to continue after freeing disk space)", - "Can't create directory '%s' (Errcode: %d)", - "Character set '%s' is not a compiled character set and is not specified in the '%s' file", - "Out of resources when opening file '%s' (Errcode: %d)", - "Can't read value for symlink '%s' (Error %d)", - "Can't create symlink '%s' pointing at '%s' (Error %d)", - "Error on realpath() on '%s' (Error %d)", - "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", - "Can't change ownership of the file '%s' (Errcode: %d)", - "Can't change permissions of the file '%s' (Errcode: %d)", - "Can't seek in file '%s' (Errcode: %d)" -}; - -void init_glob_errs(void) -{ - /* This is now done statically. */ -} - -#else - -void init_glob_errs() -{ - EE(EE_CANTCREATEFILE) = "Can't create/write to file '%s' (Errcode: %d)"; - EE(EE_READ) = "Error reading file '%s' (Errcode: %d)"; - EE(EE_WRITE) = "Error writing file '%s' (Errcode: %d)"; - EE(EE_BADCLOSE) = "Error on close of '%'s (Errcode: %d)"; - EE(EE_OUTOFMEMORY) = "Out of memory (Needed %u bytes)"; - EE(EE_DELETE) = "Error on delete of '%s' (Errcode: %d)"; - EE(EE_LINK) = "Error on rename of '%s' to '%s' (Errcode: %d)"; - EE(EE_EOFERR) = "Unexpected eof found when reading file '%s' (Errcode: %d)"; - EE(EE_CANTLOCK) = "Can't lock file (Errcode: %d)"; - EE(EE_CANTUNLOCK) = "Can't unlock file (Errcode: %d)"; - EE(EE_DIR) = "Can't read dir of '%s' (Errcode: %d)"; - EE(EE_STAT) = "Can't get stat of '%s' (Errcode: %d)"; - EE(EE_CANT_CHSIZE) = "Can't change size of file (Errcode: %d)"; - EE(EE_CANT_OPEN_STREAM)= "Can't open stream from handle (Errcode: %d)"; - EE(EE_GETWD) = "Can't get working directory (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) = "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"; - EE(EE_OUT_OF_FILERESOURCES)="Out of resources when opening file '%s' (Errcode: %d)"; - EE(EE_CANT_READLINK)= "Can't read value for symlink '%s' (Error %d)"; - EE(EE_CANT_SYMLINK)= "Can't create symlink '%s' pointing at '%s' (Error %d)"; - EE(EE_REALPATH)= "Error on realpath() on '%s' (Error %d)"; - 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"; - EE(EE_CHANGE_OWNERSHIP) = "Can't change ownership of the file '%s' (Errcode: %d)"; - EE(EE_CHANGE_PERMISSIONS) = "Can't change permissions of the file '%s' (Errcode: %d)"; - EE(EE_CANT_SEEK) = "Can't seek in file '%s' (Errcode: %d)"; -} -#endif - -void wait_for_free_space(const char *filename, int errors) -{ - if (errors == 0) - my_error(EE_DISK_FULL,MYF(ME_BELL | ME_NOREFRESH), - filename,my_errno,MY_WAIT_FOR_USER_TO_FIX_PANIC); - if (!(errors % MY_WAIT_GIVE_USER_A_MESSAGE)) - my_printf_error(EE_DISK_FULL, - "Retry in %d secs. Message reprinted in %d secs", - MYF(ME_BELL | ME_NOREFRESH), - MY_WAIT_FOR_USER_TO_FIX_PANIC, - MY_WAIT_GIVE_USER_A_MESSAGE * MY_WAIT_FOR_USER_TO_FIX_PANIC ); - (void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC); -} - -const char **get_global_errmsgs() -{ - return globerrs; -} diff --git a/dep/mysqllite/mysys/hash.c b/dep/mysqllite/mysys/hash.c deleted file mode 100644 index f54ac1a4abb..00000000000 --- a/dep/mysqllite/mysys/hash.c +++ /dev/null @@ -1,769 +0,0 @@ -/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc. - - 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 */ - -/* The hash functions used for saveing keys */ -/* One of key_length or key_length_offset must be given */ -/* Key length of 0 isn't allowed */ - -#include "mysys_priv.h" -#include <m_string.h> -#include <m_ctype.h> -#include "hash.h" - -#define NO_RECORD ((uint) -1) -#define LOWFIND 1 -#define LOWUSED 2 -#define HIGHFIND 4 -#define HIGHUSED 8 - -typedef struct st_hash_info { - uint next; /* index to next key */ - uchar *data; /* data for current entry */ -} HASH_LINK; - -static uint my_hash_mask(my_hash_value_type hashnr, - size_t buffmax, size_t maxlength); -static void movelink(HASH_LINK *array,uint pos,uint next_link,uint newlink); -static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, - size_t length); - -static my_hash_value_type calc_hash(const HASH *hash, - const uchar *key, size_t length) -{ - ulong nr1=1, nr2=4; - hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); - return (my_hash_value_type)nr1; -} - -/** - @brief Initialize the hash - - @details - - Initialize the hash, by defining and giving valid values for - its elements. The failure to allocate memory for the - hash->array element will not result in a fatal failure. The - dynamic array that is part of the hash will allocate memory - as required during insertion. - - @param[in,out] hash The hash that is initialized - @param[in] charset The charater set information - @param[in] size The hash size - @param[in] key_offest The key offset for the hash - @param[in] key_length The length of the key used in - the hash - @param[in] get_key get the key for the hash - @param[in] free_element pointer to the function that - does cleanup - @return inidicates success or failure of initialization - @retval 0 success - @retval 1 failure -*/ -my_bool -_my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset, - ulong size, size_t key_offset, size_t key_length, - my_hash_get_key get_key, - void (*free_element)(void*), uint flags) -{ - DBUG_ENTER("my_hash_init"); - DBUG_PRINT("enter",("hash: 0x%lx size: %u", (long) hash, (uint) size)); - - hash->records=0; - hash->key_offset=key_offset; - hash->key_length=key_length; - hash->blength=1; - hash->get_key=get_key; - hash->free=free_element; - hash->flags=flags; - hash->charset=charset; - DBUG_RETURN(my_init_dynamic_array_ci(&hash->array, - sizeof(HASH_LINK), size, growth_size)); -} - - -/* - Call hash->free on all elements in hash. - - SYNOPSIS - my_hash_free_elements() - hash hash table - - NOTES: - Sets records to 0 -*/ - -static inline void my_hash_free_elements(HASH *hash) -{ - if (hash->free) - { - HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); - HASH_LINK *end= data + hash->records; - while (data < end) - (*hash->free)((data++)->data); - } - hash->records=0; -} - - -/* - Free memory used by hash. - - SYNOPSIS - my_hash_free() - hash the hash to delete elements of - - NOTES: Hash can't be reused without calling my_hash_init again. -*/ - -void my_hash_free(HASH *hash) -{ - DBUG_ENTER("my_hash_free"); - DBUG_PRINT("enter",("hash: 0x%lx", (long) hash)); - - my_hash_free_elements(hash); - hash->free= 0; - delete_dynamic(&hash->array); - hash->blength= 0; - DBUG_VOID_RETURN; -} - - -/* - Delete all elements from the hash (the hash itself is to be reused). - - SYNOPSIS - my_hash_reset() - hash the hash to delete elements of -*/ - -void my_hash_reset(HASH *hash) -{ - DBUG_ENTER("my_hash_reset"); - DBUG_PRINT("enter",("hash: 0x%lxd", (long) hash)); - - my_hash_free_elements(hash); - reset_dynamic(&hash->array); - /* Set row pointers so that the hash can be reused at once */ - hash->blength= 1; - DBUG_VOID_RETURN; -} - -/* some helper functions */ - -/* - This function is char* instead of uchar* as HPUX11 compiler can't - handle inline functions that are not defined as native types -*/ - -static inline char* -my_hash_key(const HASH *hash, const uchar *record, size_t *length, - my_bool first) -{ - if (hash->get_key) - return (char*) (*hash->get_key)(record,length,first); - *length=hash->key_length; - return (char*) record+hash->key_offset; -} - - /* Calculate pos according to keys */ - -static uint my_hash_mask(my_hash_value_type hashnr, size_t buffmax, - size_t maxlength) -{ - if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1)); - return (hashnr & ((buffmax >> 1) -1)); -} - -static uint my_hash_rec_mask(const HASH *hash, HASH_LINK *pos, - size_t buffmax, size_t maxlength) -{ - size_t length; - uchar *key= (uchar*) my_hash_key(hash, pos->data, &length, 0); - return my_hash_mask(calc_hash(hash, key, length), buffmax, maxlength); -} - - - -/* for compilers which can not handle inline */ -static -#if !defined(__USLC__) && !defined(__sgi) -inline -#endif -my_hash_value_type rec_hashnr(HASH *hash,const uchar *record) -{ - size_t length; - uchar *key= (uchar*) my_hash_key(hash, record, &length, 0); - return calc_hash(hash,key,length); -} - - -uchar* my_hash_search(const HASH *hash, const uchar *key, size_t length) -{ - HASH_SEARCH_STATE state; - return my_hash_first(hash, key, length, &state); -} - -uchar* my_hash_search_using_hash_value(const HASH *hash, - my_hash_value_type hash_value, - const uchar *key, - size_t length) -{ - HASH_SEARCH_STATE state; - return my_hash_first_from_hash_value(hash, hash_value, - key, length, &state); -} - -my_hash_value_type my_calc_hash(const HASH *hash, - const uchar *key, size_t length) -{ - return calc_hash(hash, key, length ? length : hash->key_length); -} - - -/* - Search after a record based on a key - - NOTE - Assigns the number of the found record to HASH_SEARCH_STATE state -*/ - -uchar* my_hash_first(const HASH *hash, const uchar *key, size_t length, - HASH_SEARCH_STATE *current_record) -{ - uchar *res; - if (my_hash_inited(hash)) - res= my_hash_first_from_hash_value(hash, - calc_hash(hash, key, length ? length : hash->key_length), - key, length, current_record); - else - res= 0; - return res; -} - - -uchar* my_hash_first_from_hash_value(const HASH *hash, - my_hash_value_type hash_value, - const uchar *key, - size_t length, - HASH_SEARCH_STATE *current_record) -{ - HASH_LINK *pos; - uint flag,idx; - DBUG_ENTER("my_hash_first_from_hash_value"); - - flag=1; - if (hash->records) - { - idx= my_hash_mask(hash_value, - hash->blength, hash->records); - do - { - pos= dynamic_element(&hash->array,idx,HASH_LINK*); - if (!hashcmp(hash,pos,key,length)) - { - DBUG_PRINT("exit",("found key at %d",idx)); - *current_record= idx; - DBUG_RETURN (pos->data); - } - if (flag) - { - flag=0; /* Reset flag */ - if (my_hash_rec_mask(hash, pos, hash->blength, hash->records) != idx) - break; /* Wrong link */ - } - } - while ((idx=pos->next) != NO_RECORD); - } - *current_record= NO_RECORD; - DBUG_RETURN(0); -} - - /* Get next record with identical key */ - /* Can only be called if previous calls was my_hash_search */ - -uchar* my_hash_next(const HASH *hash, const uchar *key, size_t length, - HASH_SEARCH_STATE *current_record) -{ - HASH_LINK *pos; - uint idx; - - if (*current_record != NO_RECORD) - { - HASH_LINK *data=dynamic_element(&hash->array,0,HASH_LINK*); - for (idx=data[*current_record].next; idx != NO_RECORD ; idx=pos->next) - { - pos=data+idx; - if (!hashcmp(hash,pos,key,length)) - { - *current_record= idx; - return pos->data; - } - } - *current_record= NO_RECORD; - } - return 0; -} - - - /* Change link from pos to new_link */ - -static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) -{ - HASH_LINK *old_link; - do - { - old_link=array+next_link; - } - while ((next_link=old_link->next) != find); - old_link->next= newlink; - return; -} - -/* - Compare a key in a record to a whole key. Return 0 if identical - - SYNOPSIS - hashcmp() - hash hash table - pos position of hash record to use in comparison - key key for comparison - length length of key - - NOTES: - If length is 0, comparison is done using the length of the - record being compared against. - - RETURN - = 0 key of record == key - != 0 key of record != key - */ - -static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, - size_t length) -{ - size_t rec_keylength; - uchar *rec_key= (uchar*) my_hash_key(hash, pos->data, &rec_keylength, 1); - return ((length && length != rec_keylength) || - my_strnncoll(hash->charset, (uchar*) rec_key, rec_keylength, - (uchar*) key, rec_keylength)); -} - - - /* Write a hash-key to the hash-index */ - -my_bool my_hash_insert(HASH *info, const uchar *record) -{ - int flag; - size_t idx,halfbuff,first_index; - my_hash_value_type hash_nr; - uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); - HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; - - if (HASH_UNIQUE & info->flags) - { - uchar *key= (uchar*) my_hash_key(info, record, &idx, 1); - if (my_hash_search(info, key, idx)) - return(TRUE); /* Duplicate entry */ - } - - flag=0; - if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) - return(TRUE); /* No more memory */ - - data=dynamic_element(&info->array,0,HASH_LINK*); - halfbuff= info->blength >> 1; - - idx=first_index=info->records-halfbuff; - if (idx != info->records) /* If some records */ - { - do - { - pos=data+idx; - hash_nr=rec_hashnr(info,pos->data); - if (flag == 0) /* First loop; Check if ok */ - if (my_hash_mask(hash_nr, info->blength, info->records) != first_index) - break; - if (!(hash_nr & halfbuff)) - { /* Key will not move */ - if (!(flag & LOWFIND)) - { - if (flag & HIGHFIND) - { - flag=LOWFIND | HIGHFIND; - /* key shall be moved to the current empty position */ - gpos=empty; - ptr_to_rec=pos->data; - empty=pos; /* This place is now free */ - } - else - { - flag=LOWFIND | LOWUSED; /* key isn't changed */ - gpos=pos; - ptr_to_rec=pos->data; - } - } - else - { - if (!(flag & LOWUSED)) - { - /* Change link of previous LOW-key */ - gpos->data=ptr_to_rec; - gpos->next= (uint) (pos-data); - flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED); - } - gpos=pos; - ptr_to_rec=pos->data; - } - } - else - { /* key will be moved */ - if (!(flag & HIGHFIND)) - { - flag= (flag & LOWFIND) | HIGHFIND; - /* key shall be moved to the last (empty) position */ - gpos2 = empty; empty=pos; - ptr_to_rec2=pos->data; - } - else - { - if (!(flag & HIGHUSED)) - { - /* Change link of previous hash-key and save */ - gpos2->data=ptr_to_rec2; - gpos2->next=(uint) (pos-data); - flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED); - } - gpos2=pos; - ptr_to_rec2=pos->data; - } - } - } - while ((idx=pos->next) != NO_RECORD); - - if ((flag & (LOWFIND | LOWUSED)) == LOWFIND) - { - gpos->data=ptr_to_rec; - gpos->next=NO_RECORD; - } - if ((flag & (HIGHFIND | HIGHUSED)) == HIGHFIND) - { - gpos2->data=ptr_to_rec2; - gpos2->next=NO_RECORD; - } - } - /* Check if we are at the empty position */ - - idx= my_hash_mask(rec_hashnr(info, record), info->blength, info->records + 1); - pos=data+idx; - if (pos == empty) - { - pos->data=(uchar*) record; - pos->next=NO_RECORD; - } - else - { - /* Check if more records in same hash-nr family */ - empty[0]=pos[0]; - gpos= data + my_hash_rec_mask(info, pos, info->blength, info->records + 1); - if (pos == gpos) - { - pos->data=(uchar*) record; - pos->next=(uint) (empty - data); - } - else - { - pos->data=(uchar*) record; - pos->next=NO_RECORD; - movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data)); - } - } - if (++info->records == info->blength) - info->blength+= info->blength; - return(0); -} - - -/****************************************************************************** -** Remove one record from hash-table. The record with the same record -** ptr is removed. -** if there is a free-function it's called for record if found -******************************************************************************/ - -my_bool my_hash_delete(HASH *hash, uchar *record) -{ - uint blength,pos2,idx,empty_index; - my_hash_value_type pos_hashnr, lastpos_hashnr; - HASH_LINK *data,*lastpos,*gpos,*pos,*pos3,*empty; - DBUG_ENTER("my_hash_delete"); - if (!hash->records) - DBUG_RETURN(1); - - blength=hash->blength; - data=dynamic_element(&hash->array,0,HASH_LINK*); - /* Search after record with key */ - pos= data + my_hash_mask(rec_hashnr(hash, record), blength, hash->records); - gpos = 0; - - while (pos->data != record) - { - gpos=pos; - if (pos->next == NO_RECORD) - DBUG_RETURN(1); /* Key not found */ - pos=data+pos->next; - } - - if ( --(hash->records) < hash->blength >> 1) hash->blength>>=1; - lastpos=data+hash->records; - - /* Remove link to record */ - empty=pos; empty_index=(uint) (empty-data); - if (gpos) - gpos->next=pos->next; /* unlink current ptr */ - else if (pos->next != NO_RECORD) - { - empty=data+(empty_index=pos->next); - pos->data=empty->data; - pos->next=empty->next; - } - - if (empty == lastpos) /* last key at wrong pos or no next link */ - goto exit; - - /* Move the last key (lastpos) */ - lastpos_hashnr=rec_hashnr(hash,lastpos->data); - /* pos is where lastpos should be */ - pos= data + my_hash_mask(lastpos_hashnr, hash->blength, hash->records); - if (pos == empty) /* Move to empty position. */ - { - empty[0]=lastpos[0]; - goto exit; - } - pos_hashnr=rec_hashnr(hash,pos->data); - /* pos3 is where the pos should be */ - pos3= data + my_hash_mask(pos_hashnr, hash->blength, hash->records); - if (pos != pos3) - { /* pos is on wrong posit */ - empty[0]=pos[0]; /* Save it here */ - pos[0]=lastpos[0]; /* This should be here */ - movelink(data,(uint) (pos-data),(uint) (pos3-data),empty_index); - goto exit; - } - pos2= my_hash_mask(lastpos_hashnr, blength, hash->records + 1); - if (pos2 == my_hash_mask(pos_hashnr, blength, hash->records + 1)) - { /* Identical key-positions */ - if (pos2 != hash->records) - { - empty[0]=lastpos[0]; - movelink(data,(uint) (lastpos-data),(uint) (pos-data),empty_index); - goto exit; - } - idx= (uint) (pos-data); /* Link pos->next after lastpos */ - } - else idx= NO_RECORD; /* Different positions merge */ - - empty[0]=lastpos[0]; - movelink(data,idx,empty_index,pos->next); - pos->next=empty_index; - -exit: - (void) pop_dynamic(&hash->array); - if (hash->free) - (*hash->free)((uchar*) record); - DBUG_RETURN(0); -} - - /* - Update keys when record has changed. - This is much more efficent than using a delete & insert. - */ - -my_bool my_hash_update(HASH *hash, uchar *record, uchar *old_key, - size_t old_key_length) -{ - uint new_index,new_pos_index,blength,records; - size_t idx,empty; - HASH_LINK org_link,*data,*previous,*pos; - DBUG_ENTER("my_hash_update"); - - if (HASH_UNIQUE & hash->flags) - { - HASH_SEARCH_STATE state; - uchar *found, *new_key= (uchar*) my_hash_key(hash, record, &idx, 1); - if ((found= my_hash_first(hash, new_key, idx, &state))) - { - do - { - if (found != record) - DBUG_RETURN(1); /* Duplicate entry */ - } - while ((found= my_hash_next(hash, new_key, idx, &state))); - } - } - - data=dynamic_element(&hash->array,0,HASH_LINK*); - blength=hash->blength; records=hash->records; - - /* Search after record with key */ - - idx= my_hash_mask(calc_hash(hash, old_key, (old_key_length ? - old_key_length : - hash->key_length)), - blength, records); - new_index= my_hash_mask(rec_hashnr(hash, record), blength, records); - if (idx == new_index) - DBUG_RETURN(0); /* Nothing to do (No record check) */ - previous=0; - for (;;) - { - - if ((pos= data+idx)->data == record) - break; - previous=pos; - if ((idx=pos->next) == NO_RECORD) - DBUG_RETURN(1); /* Not found in links */ - } - org_link= *pos; - empty=idx; - - /* Relink record from current chain */ - - if (!previous) - { - if (pos->next != NO_RECORD) - { - empty=pos->next; - *pos= data[pos->next]; - } - } - else - previous->next=pos->next; /* unlink pos */ - - /* Move data to correct position */ - if (new_index == empty) - { - /* - At this point record is unlinked from the old chain, thus it holds - random position. By the chance this position is equal to position - for the first element in the new chain. That means updated record - is the only record in the new chain. - */ - if (empty != idx) - { - /* - Record was moved while unlinking it from the old chain. - Copy data to a new position. - */ - data[empty]= org_link; - } - data[empty].next= NO_RECORD; - DBUG_RETURN(0); - } - pos=data+new_index; - new_pos_index= my_hash_rec_mask(hash, pos, blength, records); - if (new_index != new_pos_index) - { /* Other record in wrong position */ - data[empty] = *pos; - movelink(data,new_index,new_pos_index,empty); - org_link.next=NO_RECORD; - data[new_index]= org_link; - } - else - { /* Link in chain at right position */ - org_link.next=data[new_index].next; - data[empty]=org_link; - data[new_index].next=empty; - } - DBUG_RETURN(0); -} - - -uchar *my_hash_element(HASH *hash, ulong idx) -{ - if (idx < hash->records) - return dynamic_element(&hash->array,idx,HASH_LINK*)->data; - return 0; -} - - -/* - Replace old row with new row. This should only be used when key - isn't changed -*/ - -void my_hash_replace(HASH *hash, HASH_SEARCH_STATE *current_record, - uchar *new_row) -{ - if (*current_record != NO_RECORD) /* Safety */ - dynamic_element(&hash->array, *current_record, HASH_LINK*)->data= new_row; -} - - -#ifndef DBUG_OFF - -my_bool my_hash_check(HASH *hash) -{ - int error; - uint i,rec_link,found,max_links,seek,links,idx; - uint records,blength; - HASH_LINK *data,*hash_info; - - records=hash->records; blength=hash->blength; - data=dynamic_element(&hash->array,0,HASH_LINK*); - error=0; - - for (i=found=max_links=seek=0 ; i < records ; i++) - { - if (my_hash_rec_mask(hash, data + i, blength, records) == i) - { - found++; seek++; links=1; - for (idx=data[i].next ; - idx != NO_RECORD && found < records + 1; - idx=hash_info->next) - { - if (idx >= records) - { - DBUG_PRINT("error", - ("Found pointer outside array to %d from link starting at %d", - idx,i)); - error=1; - } - hash_info=data+idx; - seek+= ++links; - if ((rec_link= my_hash_rec_mask(hash, hash_info, - blength, records)) != i) - { - DBUG_PRINT("error", ("Record in wrong link at %d: Start %d " - "Record: 0x%lx Record-link %d", - idx, i, (long) hash_info->data, rec_link)); - error=1; - } - else - found++; - } - if (links > max_links) max_links=links; - } - } - if (found != records) - { - DBUG_PRINT("error",("Found %u of %u records", found, records)); - error=1; - } - if (records) - DBUG_PRINT("info", - ("records: %u seeks: %d max links: %d hitrate: %.2f", - records,seek,max_links,(float) seek / (float) records)); - return error; -} -#endif diff --git a/dep/mysqllite/mysys/lf_alloc-pin.c b/dep/mysqllite/mysys/lf_alloc-pin.c deleted file mode 100644 index 4ed01ac8083..00000000000 --- a/dep/mysqllite/mysys/lf_alloc-pin.c +++ /dev/null @@ -1,527 +0,0 @@ -/* QQ: TODO multi-pinbox */ -/* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. - - 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 */ - -/* - wait-free concurrent allocator based on pinning addresses - - It works as follows: every thread (strictly speaking - every CPU, but - it's too difficult to do) has a small array of pointers. They're called - "pins". Before using an object its address must be stored in this array - (pinned). When an object is no longer necessary its address must be - removed from this array (unpinned). When a thread wants to free() an - object it scans all pins of all threads to see if somebody has this - object pinned. If yes - the object is not freed (but stored in a - "purgatory"). To reduce the cost of a single free() pins are not scanned - on every free() but only added to (thread-local) purgatory. On every - LF_PURGATORY_SIZE free() purgatory is scanned and all unpinned objects - are freed. - - Pins are used to solve ABA problem. To use pins one must obey - a pinning protocol: - - 1. Let's assume that PTR is a shared pointer to an object. Shared means - that any thread may modify it anytime to point to a different object - and free the old object. Later the freed object may be potentially - allocated by another thread. If we're unlucky that other thread may - set PTR to point to this object again. This is ABA problem. - 2. Create a local pointer LOCAL_PTR. - 3. Pin the PTR in a loop: - do - { - LOCAL_PTR= PTR; - pin(PTR, PIN_NUMBER); - } while (LOCAL_PTR != PTR) - 4. It is guaranteed that after the loop has ended, LOCAL_PTR - points to an object (or NULL, if PTR may be NULL), that - will never be freed. It is not guaranteed though - that LOCAL_PTR == PTR (as PTR can change any time) - 5. When done working with the object, remove the pin: - unpin(PIN_NUMBER) - 6. When copying pins (as in the list traversing loop: - pin(CUR, 1); - while () - { - do // standard - { // pinning - NEXT=CUR->next; // loop - pin(NEXT, 0); // see #3 - } while (NEXT != CUR->next); // above - ... - ... - CUR=NEXT; - pin(CUR, 1); // copy pin[0] to pin[1] - } - which keeps CUR address constantly pinned), note than pins may be - copied only upwards (!!!), that is pin[N] to pin[M], M > N. - 7. Don't keep the object pinned longer than necessary - the number of - pins you have is limited (and small), keeping an object pinned - prevents its reuse and cause unnecessary mallocs. - - Explanations: - - 3. The loop is important. The following can occur: - thread1> LOCAL_PTR= PTR - thread2> free(PTR); PTR=0; - thread1> pin(PTR, PIN_NUMBER); - now thread1 cannot access LOCAL_PTR, even if it's pinned, - because it points to a freed memory. That is, it *must* - verify that it has indeed pinned PTR, the shared pointer. - - 6. When a thread wants to free some LOCAL_PTR, and it scans - all lists of pins to see whether it's pinned, it does it - upwards, from low pin numbers to high. Thus another thread - must copy an address from one pin to another in the same - direction - upwards, otherwise the scanning thread may - miss it. - - Implementation details: - - Pins are given away from a "pinbox". Pinbox is stack-based allocator. - It used dynarray for storing pins, new elements are allocated by dynarray - as necessary, old are pushed in the stack for reuse. ABA is solved by - versioning a pointer - because we use an array, a pointer to pins is 16 bit, - upper 16 bits are used for a version. - - It is assumed that pins belong to a THD and are not transferable - between THD's (LF_PINS::stack_ends_here being a primary reason - for this limitation). -*/ -#include <my_global.h> -#include <my_sys.h> -#include <lf.h> - -#define LF_PINBOX_MAX_PINS 65536 - -static void _lf_pinbox_real_free(LF_PINS *pins); - -/* - Initialize a pinbox. Normally called from lf_alloc_init. - See the latter for details. -*/ -void lf_pinbox_init(LF_PINBOX *pinbox, uint free_ptr_offset, - lf_pinbox_free_func *free_func, void *free_func_arg) -{ - DBUG_ASSERT(free_ptr_offset % sizeof(void *) == 0); - compile_time_assert(sizeof(LF_PINS) == 64); - lf_dynarray_init(&pinbox->pinarray, sizeof(LF_PINS)); - pinbox->pinstack_top_ver= 0; - pinbox->pins_in_array= 0; - pinbox->free_ptr_offset= free_ptr_offset; - pinbox->free_func= free_func; - pinbox->free_func_arg= free_func_arg; -} - -void lf_pinbox_destroy(LF_PINBOX *pinbox) -{ - lf_dynarray_destroy(&pinbox->pinarray); -} - -/* - Get pins from a pinbox. Usually called via lf_alloc_get_pins() or - lf_hash_get_pins(). - - SYNOPSYS - pinbox - - - DESCRIPTION - get a new LF_PINS structure from a stack of unused pins, - or allocate a new one out of dynarray. - - NOTE - It is assumed that pins belong to a thread and are not transferable - between threads. -*/ -LF_PINS *_lf_pinbox_get_pins(LF_PINBOX *pinbox) -{ - uint32 pins, next, top_ver; - LF_PINS *el; - /* - We have an array of max. 64k elements. - The highest index currently allocated is pinbox->pins_in_array. - Freed elements are in a lifo stack, pinstack_top_ver. - pinstack_top_ver is 32 bits; 16 low bits are the index in the - array, to the first element of the list. 16 high bits are a version - (every time the 16 low bits are updated, the 16 high bits are - incremented). Versioniong prevents the ABA problem. - */ - top_ver= pinbox->pinstack_top_ver; - do - { - if (!(pins= top_ver % LF_PINBOX_MAX_PINS)) - { - /* the stack of free elements is empty */ - pins= my_atomic_add32((int32 volatile*) &pinbox->pins_in_array, 1)+1; - if (unlikely(pins >= LF_PINBOX_MAX_PINS)) - return 0; - /* - note that the first allocated element has index 1 (pins==1). - index 0 is reserved to mean "NULL pointer" - */ - el= (LF_PINS *)_lf_dynarray_lvalue(&pinbox->pinarray, pins); - if (unlikely(!el)) - return 0; - break; - } - el= (LF_PINS *)_lf_dynarray_value(&pinbox->pinarray, pins); - next= el->link; - } while (!my_atomic_cas32((int32 volatile*) &pinbox->pinstack_top_ver, - (int32*) &top_ver, - top_ver-pins+next+LF_PINBOX_MAX_PINS)); - /* - set el->link to the index of el in the dynarray (el->link has two usages: - - if element is allocated, it's its own index - - if element is free, it's its next element in the free stack - */ - el->link= pins; - el->purgatory_count= 0; - el->pinbox= pinbox; - el->stack_ends_here= & my_thread_var->stack_ends_here; - return el; -} - -/* - Put pins back to a pinbox. Usually called via lf_alloc_put_pins() or - lf_hash_put_pins(). - - DESCRIPTION - empty the purgatory (XXX deadlock warning below!), - push LF_PINS structure to a stack -*/ -void _lf_pinbox_put_pins(LF_PINS *pins) -{ - LF_PINBOX *pinbox= pins->pinbox; - uint32 top_ver, nr; - nr= pins->link; -#ifdef MY_LF_EXTRA_DEBUG - { - int i; - for (i= 0; i < LF_PINBOX_PINS; i++) - DBUG_ASSERT(pins->pin[i] == 0); - } -#endif - /* - XXX this will deadlock if other threads will wait for - the caller to do something after _lf_pinbox_put_pins(), - and they would have pinned addresses that the caller wants to free. - Thus: only free pins when all work is done and nobody can wait for you!!! - */ - while (pins->purgatory_count) - { - _lf_pinbox_real_free(pins); - if (pins->purgatory_count) - { - my_atomic_rwlock_wrunlock(&pins->pinbox->pinarray.lock); - pthread_yield(); - my_atomic_rwlock_wrlock(&pins->pinbox->pinarray.lock); - } - } - top_ver= pinbox->pinstack_top_ver; - do - { - pins->link= top_ver % LF_PINBOX_MAX_PINS; - } while (!my_atomic_cas32((int32 volatile*) &pinbox->pinstack_top_ver, - (int32*) &top_ver, - top_ver-pins->link+nr+LF_PINBOX_MAX_PINS)); - return; -} - -static int ptr_cmp(void **a, void **b) -{ - return *a < *b ? -1 : *a == *b ? 0 : 1; -} - -#define add_to_purgatory(PINS, ADDR) \ - do \ - { \ - *(void **)((char *)(ADDR)+(PINS)->pinbox->free_ptr_offset)= \ - (PINS)->purgatory; \ - (PINS)->purgatory= (ADDR); \ - (PINS)->purgatory_count++; \ - } while (0) - -/* - Free an object allocated via pinbox allocator - - DESCRIPTION - add an object to purgatory. if necessary, call _lf_pinbox_real_free() - to actually free something. -*/ -void _lf_pinbox_free(LF_PINS *pins, void *addr) -{ - add_to_purgatory(pins, addr); - if (pins->purgatory_count % LF_PURGATORY_SIZE) - _lf_pinbox_real_free(pins); -} - -struct st_harvester { - void **granary; - int npins; -}; - -/* - callback for _lf_dynarray_iterate: - scan all pins of all threads and accumulate all pins -*/ -static int harvest_pins(LF_PINS *el, struct st_harvester *hv) -{ - int i; - LF_PINS *el_end= el+min(hv->npins, LF_DYNARRAY_LEVEL_LENGTH); - for (; el < el_end; el++) - { - for (i= 0; i < LF_PINBOX_PINS; i++) - { - void *p= el->pin[i]; - if (p) - *hv->granary++= p; - } - } - /* - hv->npins may become negative below, but it means that - we're on the last dynarray page and harvest_pins() won't be - called again. We don't bother to make hv->npins() correct - (that is 0) in this case. - */ - hv->npins-= LF_DYNARRAY_LEVEL_LENGTH; - return 0; -} - -/* - callback for _lf_dynarray_iterate: - scan all pins of all threads and see if addr is present there -*/ -static int match_pins(LF_PINS *el, void *addr) -{ - int i; - LF_PINS *el_end= el+LF_DYNARRAY_LEVEL_LENGTH; - for (; el < el_end; el++) - for (i= 0; i < LF_PINBOX_PINS; i++) - if (el->pin[i] == addr) - return 1; - return 0; -} - -#if STACK_DIRECTION < 0 -#define available_stack_size(CUR,END) (long) ((char*)(CUR) - (char*)(END)) -#else -#define available_stack_size(CUR,END) (long) ((char*)(END) - (char*)(CUR)) -#endif - -#define next_node(P, X) (*((uchar * volatile *)(((uchar *)(X)) + (P)->free_ptr_offset))) -#define anext_node(X) next_node(&allocator->pinbox, (X)) - -/* - Scan the purgatory and free everything that can be freed -*/ -static void _lf_pinbox_real_free(LF_PINS *pins) -{ - int npins, alloca_size; - void *list, **addr; - void *first= NULL, *last= NULL; - LF_PINBOX *pinbox= pins->pinbox; - - npins= pinbox->pins_in_array+1; - -#ifdef HAVE_ALLOCA - alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins; - /* create a sorted list of pinned addresses, to speed up searches */ - if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size) - { - struct st_harvester hv; - addr= (void **) alloca(alloca_size); - hv.granary= addr; - hv.npins= npins; - /* scan the dynarray and accumulate all pinned addresses */ - _lf_dynarray_iterate(&pinbox->pinarray, - (lf_dynarray_func)harvest_pins, &hv); - - npins= hv.granary-addr; - /* and sort them */ - if (npins) - qsort(addr, npins, sizeof(void *), (qsort_cmp)ptr_cmp); - } - else -#endif - addr= 0; - - list= pins->purgatory; - pins->purgatory= 0; - pins->purgatory_count= 0; - while (list) - { - void *cur= list; - list= *(void **)((char *)cur+pinbox->free_ptr_offset); - if (npins) - { - if (addr) /* use binary search */ - { - void **a, **b, **c; - for (a= addr, b= addr+npins-1, c= a+(b-a)/2; (b-a) > 1; c= a+(b-a)/2) - if (cur == *c) - a= b= c; - else if (cur > *c) - a= c; - else - b= c; - if (cur == *a || cur == *b) - goto found; - } - else /* no alloca - no cookie. linear search here */ - { - if (_lf_dynarray_iterate(&pinbox->pinarray, - (lf_dynarray_func)match_pins, cur)) - goto found; - } - } - /* not pinned - freeing */ - if (last) - last= next_node(pinbox, last)= (uchar *)cur; - else - first= last= (uchar *)cur; - continue; -found: - /* pinned - keeping */ - add_to_purgatory(pins, cur); - } - if (last) - pinbox->free_func(first, last, pinbox->free_func_arg); -} - -/* lock-free memory allocator for fixed-size objects */ - -LF_REQUIRE_PINS(1) - -/* - callback for _lf_pinbox_real_free to free a list of unpinned objects - - add it back to the allocator stack - - DESCRIPTION - 'first' and 'last' are the ends of the linked list of nodes: - first->el->el->....->el->last. Use first==last to free only one element. -*/ -static void alloc_free(uchar *first, - uchar volatile *last, - LF_ALLOCATOR *allocator) -{ - /* - we need a union here to access type-punned pointer reliably. - otherwise gcc -fstrict-aliasing will not see 'tmp' changed in the loop - */ - union { uchar * node; void *ptr; } tmp; - tmp.node= allocator->top; - do - { - anext_node(last)= tmp.node; - } while (!my_atomic_casptr((void **)(char *)&allocator->top, - (void **)&tmp.ptr, first) && LF_BACKOFF); -} - -/* - initialize lock-free allocator - - SYNOPSYS - allocator - - size a size of an object to allocate - free_ptr_offset an offset inside the object to a sizeof(void *) - memory that is guaranteed to be unused after - the object is put in the purgatory. Unused by ANY - thread, not only the purgatory owner. - This memory will be used to link waiting-to-be-freed - objects in a purgatory list. -*/ -void lf_alloc_init(LF_ALLOCATOR *allocator, uint size, uint free_ptr_offset) -{ - lf_pinbox_init(&allocator->pinbox, free_ptr_offset, - (lf_pinbox_free_func *)alloc_free, allocator); - allocator->top= 0; - allocator->mallocs= 0; - allocator->element_size= size; - DBUG_ASSERT(size >= sizeof(void*) + free_ptr_offset); -} - -/* - destroy the allocator, free everything that's in it - - NOTE - As every other init/destroy function here and elsewhere it - is not thread safe. No, this function is no different, ensure - that no thread needs the allocator before destroying it. - We are not responsible for any damage that may be caused by - accessing the allocator when it is being or has been destroyed. - Oh yes, and don't put your cat in a microwave. -*/ -void lf_alloc_destroy(LF_ALLOCATOR *allocator) -{ - uchar *node= allocator->top; - while (node) - { - uchar *tmp= anext_node(node); - my_free(node); - node= tmp; - } - lf_pinbox_destroy(&allocator->pinbox); - allocator->top= 0; -} - -/* - Allocate and return an new object. - - DESCRIPTION - Pop an unused object from the stack or malloc it is the stack is empty. - pin[0] is used, it's removed on return. -*/ -void *_lf_alloc_new(LF_PINS *pins) -{ - LF_ALLOCATOR *allocator= (LF_ALLOCATOR *)(pins->pinbox->free_func_arg); - uchar *node; - for (;;) - { - do - { - node= allocator->top; - _lf_pin(pins, 0, node); - } while (node != allocator->top && LF_BACKOFF); - if (!node) - { - node= (void *)my_malloc(allocator->element_size, MYF(MY_WME)); -#ifdef MY_LF_EXTRA_DEBUG - if (likely(node != 0)) - my_atomic_add32(&allocator->mallocs, 1); -#endif - break; - } - if (my_atomic_casptr((void **)(char *)&allocator->top, - (void *)&node, anext_node(node))) - break; - } - _lf_unpin(pins, 0); - return node; -} - -/* - count the number of objects in a pool. - - NOTE - This is NOT thread-safe !!! -*/ -uint lf_alloc_pool_count(LF_ALLOCATOR *allocator) -{ - uint i; - uchar *node; - for (node= allocator->top, i= 0; node; node= anext_node(node), i++) - /* no op */; - return i; -} - diff --git a/dep/mysqllite/mysys/lf_dynarray.c b/dep/mysqllite/mysys/lf_dynarray.c deleted file mode 100644 index 0941c8762bb..00000000000 --- a/dep/mysqllite/mysys/lf_dynarray.c +++ /dev/null @@ -1,207 +0,0 @@ -/* 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 */ - -/* - Analog of DYNAMIC_ARRAY that never reallocs - (so no pointer into the array may ever become invalid). - - Memory is allocated in non-contiguous chunks. - This data structure is not space efficient for sparse arrays. - - Every element is aligned to sizeof(element) boundary - (to avoid false sharing if element is big enough). - - LF_DYNARRAY is a recursive structure. On the zero level - LF_DYNARRAY::level[0] it's an array of LF_DYNARRAY_LEVEL_LENGTH elements, - on the first level it's an array of LF_DYNARRAY_LEVEL_LENGTH pointers - to arrays of elements, on the second level it's an array of pointers - to arrays of pointers to arrays of elements. And so on. - - With four levels the number of elements is limited to 4311810304 - (but as in all functions index is uint, the real limit is 2^32-1) - - Actually, it's wait-free, not lock-free ;-) -*/ - -#include <my_global.h> -#include <m_string.h> -#include <my_sys.h> -#include <lf.h> - -void lf_dynarray_init(LF_DYNARRAY *array, uint element_size) -{ - bzero(array, sizeof(*array)); - array->size_of_element= element_size; - my_atomic_rwlock_init(&array->lock); -} - -static void recursive_free(void **alloc, int level) -{ - if (!alloc) - return; - - if (level) - { - int i; - for (i= 0; i < LF_DYNARRAY_LEVEL_LENGTH; i++) - recursive_free(alloc[i], level-1); - my_free(alloc); - } - else - my_free(alloc[-1]); -} - -void lf_dynarray_destroy(LF_DYNARRAY *array) -{ - int i; - for (i= 0; i < LF_DYNARRAY_LEVELS; i++) - recursive_free(array->level[i], i); - my_atomic_rwlock_destroy(&array->lock); -} - -static const ulong dynarray_idxes_in_prev_levels[LF_DYNARRAY_LEVELS]= -{ - 0, /* +1 here to to avoid -1's below */ - LF_DYNARRAY_LEVEL_LENGTH, - LF_DYNARRAY_LEVEL_LENGTH * LF_DYNARRAY_LEVEL_LENGTH + - LF_DYNARRAY_LEVEL_LENGTH, - LF_DYNARRAY_LEVEL_LENGTH * LF_DYNARRAY_LEVEL_LENGTH * - LF_DYNARRAY_LEVEL_LENGTH + LF_DYNARRAY_LEVEL_LENGTH * - LF_DYNARRAY_LEVEL_LENGTH + LF_DYNARRAY_LEVEL_LENGTH -}; - -static const ulong dynarray_idxes_in_prev_level[LF_DYNARRAY_LEVELS]= -{ - 0, /* +1 here to to avoid -1's below */ - LF_DYNARRAY_LEVEL_LENGTH, - LF_DYNARRAY_LEVEL_LENGTH * LF_DYNARRAY_LEVEL_LENGTH, - LF_DYNARRAY_LEVEL_LENGTH * LF_DYNARRAY_LEVEL_LENGTH * - LF_DYNARRAY_LEVEL_LENGTH, -}; - -/* - Returns a valid lvalue pointer to the element number 'idx'. - Allocates memory if necessary. -*/ -void *_lf_dynarray_lvalue(LF_DYNARRAY *array, uint idx) -{ - void * ptr, * volatile * ptr_ptr= 0; - int i; - - for (i= LF_DYNARRAY_LEVELS-1; idx < dynarray_idxes_in_prev_levels[i]; i--) - /* no-op */; - ptr_ptr= &array->level[i]; - idx-= dynarray_idxes_in_prev_levels[i]; - for (; i > 0; i--) - { - if (!(ptr= *ptr_ptr)) - { - void *alloc= my_malloc(LF_DYNARRAY_LEVEL_LENGTH * sizeof(void *), - MYF(MY_WME|MY_ZEROFILL)); - if (unlikely(!alloc)) - return(NULL); - if (my_atomic_casptr(ptr_ptr, &ptr, alloc)) - ptr= alloc; - else - my_free(alloc); - } - ptr_ptr= ((void **)ptr) + idx / dynarray_idxes_in_prev_level[i]; - idx%= dynarray_idxes_in_prev_level[i]; - } - if (!(ptr= *ptr_ptr)) - { - uchar *alloc, *data; - alloc= my_malloc(LF_DYNARRAY_LEVEL_LENGTH * array->size_of_element + - max(array->size_of_element, sizeof(void *)), - MYF(MY_WME|MY_ZEROFILL)); - if (unlikely(!alloc)) - return(NULL); - /* reserve the space for free() address */ - data= alloc + sizeof(void *); - { /* alignment */ - intptr mod= ((intptr)data) % array->size_of_element; - if (mod) - data+= array->size_of_element - mod; - } - ((void **)data)[-1]= alloc; /* free() will need the original pointer */ - if (my_atomic_casptr(ptr_ptr, &ptr, data)) - ptr= data; - else - my_free(alloc); - } - return ((uchar*)ptr) + array->size_of_element * idx; -} - -/* - Returns a pointer to the element number 'idx' - or NULL if an element does not exists -*/ -void *_lf_dynarray_value(LF_DYNARRAY *array, uint idx) -{ - void * ptr, * volatile * ptr_ptr= 0; - int i; - - for (i= LF_DYNARRAY_LEVELS-1; idx < dynarray_idxes_in_prev_levels[i]; i--) - /* no-op */; - ptr_ptr= &array->level[i]; - idx-= dynarray_idxes_in_prev_levels[i]; - for (; i > 0; i--) - { - if (!(ptr= *ptr_ptr)) - return(NULL); - ptr_ptr= ((void **)ptr) + idx / dynarray_idxes_in_prev_level[i]; - idx %= dynarray_idxes_in_prev_level[i]; - } - if (!(ptr= *ptr_ptr)) - return(NULL); - return ((uchar*)ptr) + array->size_of_element * idx; -} - -static int recursive_iterate(LF_DYNARRAY *array, void *ptr, int level, - lf_dynarray_func func, void *arg) -{ - int res, i; - if (!ptr) - return 0; - if (!level) - return func(ptr, arg); - for (i= 0; i < LF_DYNARRAY_LEVEL_LENGTH; i++) - if ((res= recursive_iterate(array, ((void **)ptr)[i], level-1, func, arg))) - return res; - return 0; -} - -/* - Calls func(array, arg) on every array of LF_DYNARRAY_LEVEL_LENGTH elements - in lf_dynarray. - - DESCRIPTION - lf_dynarray consists of a set of arrays, LF_DYNARRAY_LEVEL_LENGTH elements - each. _lf_dynarray_iterate() calls user-supplied function on every array - from the set. It is the fastest way to scan the array, faster than - for (i=0; i < N; i++) { func(_lf_dynarray_value(dynarray, i)); } - - NOTE - if func() returns non-zero, the scan is aborted -*/ -int _lf_dynarray_iterate(LF_DYNARRAY *array, lf_dynarray_func func, void *arg) -{ - int i, res; - for (i= 0; i < LF_DYNARRAY_LEVELS; i++) - if ((res= recursive_iterate(array, array->level[i], i, func, arg))) - return res; - return 0; -} - diff --git a/dep/mysqllite/mysys/lf_hash.c b/dep/mysqllite/mysys/lf_hash.c deleted file mode 100644 index e7bf82fc6ca..00000000000 --- a/dep/mysqllite/mysys/lf_hash.c +++ /dev/null @@ -1,503 +0,0 @@ -/* Copyright (C) 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. - - 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 */ - -/* - extensible hash - - TODO - try to get rid of dummy nodes ? - for non-unique hash, count only _distinct_ values - (but how to do it in lf_hash_delete ?) -*/ -#include <my_global.h> -#include <m_string.h> -#include <my_sys.h> -#include <my_bit.h> -#include <lf.h> - -LF_REQUIRE_PINS(3) - -/* An element of the list */ -typedef struct { - intptr volatile link; /* a pointer to the next element in a listand a flag */ - uint32 hashnr; /* reversed hash number, for sorting */ - const uchar *key; - size_t keylen; - /* - data is stored here, directly after the keylen. - thus the pointer to data is (void*)(slist_element_ptr+1) - */ -} LF_SLIST; - -/* - a structure to pass the context (pointers two the three successive elements - in a list) from lfind to linsert/ldelete -*/ -typedef struct { - intptr volatile *prev; - LF_SLIST *curr, *next; -} CURSOR; - -/* - the last bit in LF_SLIST::link is a "deleted" flag. - the helper macros below convert it to a pure pointer or a pure flag -*/ -#define PTR(V) (LF_SLIST *)((V) & (~(intptr)1)) -#define DELETED(V) ((V) & 1) - -/* - DESCRIPTION - Search for hashnr/key/keylen in the list starting from 'head' and - position the cursor. The list is ORDER BY hashnr, key - - RETURN - 0 - not found - 1 - found - - NOTE - cursor is positioned in either case - pins[0..2] are used, they are NOT removed on return -*/ -static int lfind(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, - const uchar *key, uint keylen, CURSOR *cursor, LF_PINS *pins) -{ - uint32 cur_hashnr; - const uchar *cur_key; - uint cur_keylen; - intptr link; - -retry: - cursor->prev= (intptr *)head; - do { /* PTR() isn't necessary below, head is a dummy node */ - cursor->curr= (LF_SLIST *)(*cursor->prev); - _lf_pin(pins, 1, cursor->curr); - } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF); - for (;;) - { - if (unlikely(!cursor->curr)) - return 0; /* end of the list */ - do { - /* QQ: XXX or goto retry ? */ - link= cursor->curr->link; - cursor->next= PTR(link); - _lf_pin(pins, 0, cursor->next); - } while (link != cursor->curr->link && LF_BACKOFF); - cur_hashnr= cursor->curr->hashnr; - cur_key= cursor->curr->key; - cur_keylen= cursor->curr->keylen; - if (*cursor->prev != (intptr)cursor->curr) - { - (void)LF_BACKOFF; - goto retry; - } - if (!DELETED(link)) - { - if (cur_hashnr >= hashnr) - { - int r= 1; - if (cur_hashnr > hashnr || - (r= my_strnncoll(cs, (uchar*) cur_key, cur_keylen, (uchar*) key, - keylen)) >= 0) - return !r; - } - cursor->prev= &(cursor->curr->link); - _lf_pin(pins, 2, cursor->curr); - } - else - { - /* - we found a deleted node - be nice, help the other thread - and remove this deleted node - */ - if (my_atomic_casptr((void **)cursor->prev, - (void **)&cursor->curr, cursor->next)) - _lf_alloc_free(pins, cursor->curr); - else - { - (void)LF_BACKOFF; - goto retry; - } - } - cursor->curr= cursor->next; - _lf_pin(pins, 1, cursor->curr); - } -} - -/* - DESCRIPTION - insert a 'node' in the list that starts from 'head' in the correct - position (as found by lfind) - - RETURN - 0 - inserted - not 0 - a pointer to a duplicate (not pinned and thus unusable) - - NOTE - it uses pins[0..2], on return all pins are removed. - if there're nodes with the same key value, a new node is added before them. -*/ -static LF_SLIST *linsert(LF_SLIST * volatile *head, CHARSET_INFO *cs, - LF_SLIST *node, LF_PINS *pins, uint flags) -{ - CURSOR cursor; - int res; - - for (;;) - { - if (lfind(head, cs, node->hashnr, node->key, node->keylen, - &cursor, pins) && - (flags & LF_HASH_UNIQUE)) - { - res= 0; /* duplicate found */ - break; - } - else - { - node->link= (intptr)cursor.curr; - DBUG_ASSERT(node->link != (intptr)node); /* no circular references */ - DBUG_ASSERT(cursor.prev != &node->link); /* no circular references */ - if (my_atomic_casptr((void **)cursor.prev, (void **)&cursor.curr, node)) - { - res= 1; /* inserted ok */ - break; - } - } - } - _lf_unpin(pins, 0); - _lf_unpin(pins, 1); - _lf_unpin(pins, 2); - /* - Note that cursor.curr is not pinned here and the pointer is unreliable, - the object may dissapear anytime. But if it points to a dummy node, the - pointer is safe, because dummy nodes are never freed - initialize_bucket() - uses this fact. - */ - return res ? 0 : cursor.curr; -} - -/* - DESCRIPTION - deletes a node as identified by hashnr/keey/keylen from the list - that starts from 'head' - - RETURN - 0 - ok - 1 - not found - - NOTE - it uses pins[0..2], on return all pins are removed. -*/ -static int ldelete(LF_SLIST * volatile *head, CHARSET_INFO *cs, uint32 hashnr, - const uchar *key, uint keylen, LF_PINS *pins) -{ - CURSOR cursor; - int res; - - for (;;) - { - if (!lfind(head, cs, hashnr, key, keylen, &cursor, pins)) - { - res= 1; /* not found */ - break; - } - else - { - /* mark the node deleted */ - if (my_atomic_casptr((void **)&(cursor.curr->link), - (void **)&cursor.next, - (void *)(((intptr)cursor.next) | 1))) - { - /* and remove it from the list */ - if (my_atomic_casptr((void **)cursor.prev, - (void **)&cursor.curr, cursor.next)) - _lf_alloc_free(pins, cursor.curr); - else - { - /* - somebody already "helped" us and removed the node ? - Let's check if we need to help that someone too! - (to ensure the number of "set DELETED flag" actions - is equal to the number of "remove from the list" actions) - */ - lfind(head, cs, hashnr, key, keylen, &cursor, pins); - } - res= 0; - break; - } - } - } - _lf_unpin(pins, 0); - _lf_unpin(pins, 1); - _lf_unpin(pins, 2); - return res; -} - -/* - DESCRIPTION - searches for a node as identified by hashnr/keey/keylen in the list - that starts from 'head' - - RETURN - 0 - not found - node - found - - NOTE - it uses pins[0..2], on return the pin[2] keeps the node found - all other pins are removed. -*/ -static LF_SLIST *lsearch(LF_SLIST * volatile *head, CHARSET_INFO *cs, - uint32 hashnr, const uchar *key, uint keylen, - LF_PINS *pins) -{ - CURSOR cursor; - int res= lfind(head, cs, hashnr, key, keylen, &cursor, pins); - if (res) - _lf_pin(pins, 2, cursor.curr); - _lf_unpin(pins, 0); - _lf_unpin(pins, 1); - return res ? cursor.curr : 0; -} - -static inline const uchar* hash_key(const LF_HASH *hash, - const uchar *record, size_t *length) -{ - if (hash->get_key) - return (*hash->get_key)(record, length, 0); - *length= hash->key_length; - return record + hash->key_offset; -} - -/* - Compute the hash key value from the raw key. - - @note, that the hash value is limited to 2^31, because we need one - bit to distinguish between normal and dummy nodes. -*/ -static inline uint calc_hash(LF_HASH *hash, const uchar *key, uint keylen) -{ - ulong nr1= 1, nr2= 4; - hash->charset->coll->hash_sort(hash->charset, (uchar*) key, keylen, - &nr1, &nr2); - return nr1 & INT_MAX32; -} - -#define MAX_LOAD 1.0 /* average number of elements in a bucket */ - -static int initialize_bucket(LF_HASH *, LF_SLIST * volatile*, uint, LF_PINS *); - -/* - Initializes lf_hash, the arguments are compatible with hash_init - - @note element_size sets both the size of allocated memory block for - lf_alloc and a size of memcpy'ed block size in lf_hash_insert. Typically - they are the same, indeed. But LF_HASH::element_size can be decreased - after lf_hash_init, and then lf_alloc will allocate larger block that - lf_hash_insert will copy over. It is desireable if part of the element - is expensive to initialize - for example if there is a mutex or - DYNAMIC_ARRAY. In this case they should be initialize in the - LF_ALLOCATOR::constructor, and lf_hash_insert should not overwrite them. - See wt_init() for example. -*/ -void lf_hash_init(LF_HASH *hash, uint element_size, uint flags, - uint key_offset, uint key_length, my_hash_get_key get_key, - CHARSET_INFO *charset) -{ - lf_alloc_init(&hash->alloc, sizeof(LF_SLIST)+element_size, - offsetof(LF_SLIST, key)); - lf_dynarray_init(&hash->array, sizeof(LF_SLIST *)); - hash->size= 1; - hash->count= 0; - hash->element_size= element_size; - hash->flags= flags; - hash->charset= charset ? charset : &my_charset_bin; - hash->key_offset= key_offset; - hash->key_length= key_length; - hash->get_key= get_key; - DBUG_ASSERT(get_key ? !key_offset && !key_length : key_length); -} - -void lf_hash_destroy(LF_HASH *hash) -{ - LF_SLIST *el, **head= (LF_SLIST **)_lf_dynarray_value(&hash->array, 0); - - if (unlikely(!head)) - return; - el= *head; - - while (el) - { - intptr next= el->link; - if (el->hashnr & 1) - lf_alloc_direct_free(&hash->alloc, el); /* normal node */ - else - my_free(el); /* dummy node */ - el= (LF_SLIST *)next; - } - lf_alloc_destroy(&hash->alloc); - lf_dynarray_destroy(&hash->array); -} - -/* - DESCRIPTION - inserts a new element to a hash. it will have a _copy_ of - data, not a pointer to it. - - RETURN - 0 - inserted - 1 - didn't (unique key conflict) - -1 - out of memory - - NOTE - see linsert() for pin usage notes -*/ -int lf_hash_insert(LF_HASH *hash, LF_PINS *pins, const void *data) -{ - int csize, bucket, hashnr; - LF_SLIST *node, * volatile *el; - - lf_rwlock_by_pins(pins); - node= (LF_SLIST *)_lf_alloc_new(pins); - if (unlikely(!node)) - return -1; - memcpy(node+1, data, hash->element_size); - node->key= hash_key(hash, (uchar *)(node+1), &node->keylen); - hashnr= calc_hash(hash, node->key, node->keylen); - bucket= hashnr % hash->size; - el= _lf_dynarray_lvalue(&hash->array, bucket); - if (unlikely(!el)) - return -1; - if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins))) - return -1; - node->hashnr= my_reverse_bits(hashnr) | 1; /* normal node */ - if (linsert(el, hash->charset, node, pins, hash->flags)) - { - _lf_alloc_free(pins, node); - lf_rwunlock_by_pins(pins); - return 1; - } - csize= hash->size; - if ((my_atomic_add32(&hash->count, 1)+1.0) / csize > MAX_LOAD) - my_atomic_cas32(&hash->size, &csize, csize*2); - lf_rwunlock_by_pins(pins); - return 0; -} - -/* - DESCRIPTION - deletes an element with the given key from the hash (if a hash is - not unique and there're many elements with this key - the "first" - matching element is deleted) - RETURN - 0 - deleted - 1 - didn't (not found) - -1 - out of memory - NOTE - see ldelete() for pin usage notes -*/ -int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) -{ - LF_SLIST * volatile *el; - uint bucket, hashnr= calc_hash(hash, (uchar *)key, keylen); - - bucket= hashnr % hash->size; - lf_rwlock_by_pins(pins); - el= _lf_dynarray_lvalue(&hash->array, bucket); - if (unlikely(!el)) - return -1; - /* - note that we still need to initialize_bucket here, - we cannot return "node not found", because an old bucket of that - node may've been split and the node was assigned to a new bucket - that was never accessed before and thus is not initialized. - */ - if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins))) - return -1; - if (ldelete(el, hash->charset, my_reverse_bits(hashnr) | 1, - (uchar *)key, keylen, pins)) - { - lf_rwunlock_by_pins(pins); - return 1; - } - my_atomic_add32(&hash->count, -1); - lf_rwunlock_by_pins(pins); - return 0; -} - -/* - RETURN - a pointer to an element with the given key (if a hash is not unique and - there're many elements with this key - the "first" matching element) - NULL if nothing is found - MY_ERRPTR if OOM - - NOTE - see lsearch() for pin usage notes -*/ -void *lf_hash_search(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen) -{ - LF_SLIST * volatile *el, *found; - uint bucket, hashnr= calc_hash(hash, (uchar *)key, keylen); - - bucket= hashnr % hash->size; - lf_rwlock_by_pins(pins); - el= _lf_dynarray_lvalue(&hash->array, bucket); - if (unlikely(!el)) - return MY_ERRPTR; - if (*el == NULL && unlikely(initialize_bucket(hash, el, bucket, pins))) - return MY_ERRPTR; - found= lsearch(el, hash->charset, my_reverse_bits(hashnr) | 1, - (uchar *)key, keylen, pins); - lf_rwunlock_by_pins(pins); - return found ? found+1 : 0; -} - -static const uchar *dummy_key= (uchar*)""; - -/* - RETURN - 0 - ok - -1 - out of memory -*/ -static int initialize_bucket(LF_HASH *hash, LF_SLIST * volatile *node, - uint bucket, LF_PINS *pins) -{ - uint parent= my_clear_highest_bit(bucket); - LF_SLIST *dummy= (LF_SLIST *)my_malloc(sizeof(LF_SLIST), MYF(MY_WME)); - LF_SLIST **tmp= 0, *cur; - LF_SLIST * volatile *el= _lf_dynarray_lvalue(&hash->array, parent); - if (unlikely(!el || !dummy)) - return -1; - if (*el == NULL && bucket && - unlikely(initialize_bucket(hash, el, parent, pins))) - return -1; - dummy->hashnr= my_reverse_bits(bucket) | 0; /* dummy node */ - dummy->key= dummy_key; - dummy->keylen= 0; - if ((cur= linsert(el, hash->charset, dummy, pins, LF_HASH_UNIQUE))) - { - my_free(dummy); - dummy= cur; - } - my_atomic_casptr((void **)node, (void **)&tmp, dummy); - /* - note that if the CAS above failed (after linsert() succeeded), - it would mean that some other thread has executed linsert() for - the same dummy node, its linsert() failed, it picked up our - dummy node (in "dummy= cur") and executed the same CAS as above. - Which means that even if CAS above failed we don't need to retry, - and we should not free(dummy) - there's no memory leak here - */ - return 0; -} diff --git a/dep/mysqllite/mysys/list.c b/dep/mysqllite/mysys/list.c deleted file mode 100644 index e68fbf519d1..00000000000 --- a/dep/mysqllite/mysys/list.c +++ /dev/null @@ -1,114 +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 */ - -/* - Code for handling dubble-linked lists in C -*/ - -#include "mysys_priv.h" -#include <my_list.h> - - - - /* Add a element to start of list */ - -LIST *list_add(LIST *root, LIST *element) -{ - DBUG_ENTER("list_add"); - DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", (long) root, (long) element)); - if (root) - { - if (root->prev) /* If add in mid of list */ - root->prev->next= element; - element->prev=root->prev; - root->prev=element; - } - else - element->prev=0; - element->next=root; - DBUG_RETURN(element); /* New root */ -} - - -LIST *list_delete(LIST *root, LIST *element) -{ - if (element->prev) - element->prev->next=element->next; - else - root=element->next; - if (element->next) - element->next->prev=element->prev; - return root; -} - - -void list_free(LIST *root, uint free_data) -{ - LIST *next; - while (root) - { - next=root->next; - if (free_data) - my_free(root->data); - my_free(root); - root=next; - } -} - - -LIST *list_cons(void *data, LIST *list) -{ - LIST *new_charset=(LIST*) my_malloc(sizeof(LIST),MYF(MY_FAE)); - if (!new_charset) - return 0; - new_charset->data=data; - return list_add(list,new_charset); -} - - -LIST *list_reverse(LIST *root) -{ - LIST *last; - - last=root; - while (root) - { - last=root; - root=root->next; - last->next=last->prev; - last->prev=root; - } - return last; -} - -uint list_length(LIST *list) -{ - uint count; - for (count=0 ; list ; list=list->next, count++) ; - return count; -} - - -int list_walk(LIST *list, list_walk_action action, uchar* argument) -{ - int error=0; - while (list) - { - if ((error = (*action)(list->data,argument))) - return error; - list=list_rest(list); - } - return 0; -} diff --git a/dep/mysqllite/mysys/md5.c b/dep/mysqllite/mysys/md5.c deleted file mode 100644 index 2388cebedc4..00000000000 --- a/dep/mysqllite/mysys/md5.c +++ /dev/null @@ -1,325 +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 */ - -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to - not require an integer type which is exactly 32 bits. This work - draws on the changes for the same purpose by Tatu Ylonen - <ylo@cs.hut.fi> as part of SSH, but since I didn't actually use - that code, there is no copyright issue. I hereby disclaim - copyright in any changes I have made; this code remains in the - public domain. */ - -#include <my_global.h> -#include <m_string.h> -#include "my_md5.h" - -#include <string.h> /* for memcpy() and memset() */ - - -static void -my_MD5Transform (cvs_uint32 buf[4], const unsigned char in[64]); - -/* Little-endian byte-swapping routines. Note that these do not - depend on the size of datatypes such as uint32, nor do they require - us to detect the endianness of the machine we are running on. It - is possible they should be macros for speed, but I would be - surprised if they were a performance bottleneck for MD5. */ - -static uint32 getu32 (const unsigned char *addr) -{ - return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) - | addr[1]) << 8 | addr[0]; -} - -static void -putu32 (uint32 data, unsigned char *addr) -{ - addr[0] = (unsigned char)data; - addr[1] = (unsigned char)(data >> 8); - addr[2] = (unsigned char)(data >> 16); - addr[3] = (unsigned char)(data >> 24); -} - -/* - Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - initialization constants. -*/ -void -my_MD5Init (my_MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - Update context to reflect the concatenation of another buffer full - of bytes. -*/ -void -my_MD5Update (my_MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - uint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if ( t ) { - unsigned char *p = ctx->in + t; - - t = 64-t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - my_MD5Transform (ctx->buf, ctx->in); - buf += t; - len -= t; - } - - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - my_MD5Transform (ctx->buf, ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - Final wrapup - pad to 64-byte boundary with the bit pattern - 1 0* (64-bit count of bits processed, MSB-first) -*/ -void -my_MD5Final (unsigned char digest[16], my_MD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - my_MD5Transform (ctx->buf, ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count-8); - } - - /* Append length in bits and transform */ - putu32(ctx->bits[0], ctx->in + 56); - putu32(ctx->bits[1], ctx->in + 60); - - my_MD5Transform (ctx->buf, ctx->in); - putu32(ctx->buf[0], digest); - putu32(ctx->buf[1], digest + 4); - putu32(ctx->buf[2], digest + 8); - putu32(ctx->buf[3], digest + 12); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -#ifndef ASM_MD5 - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<<s | w>>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void -my_MD5Transform (uint32 buf[4], const unsigned char inraw[64]) -{ - register uint32 a, b, c, d; - uint32 in[16]; - int i; - - for (i = 0; i < 16; ++i) - in[i] = getu32 (inraw + 4 * i); - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} -#endif - -#ifdef TEST -/* - Simple test program. Can use it to manually run the tests from - RFC1321 for example. -*/ -#include <stdio.h> - -int -main (int argc, char **argv) -{ - my_MD5Context context; - unsigned char checksum[16]; - int i; - int j; - - if (argc < 2) - { - fprintf (stderr, "usage: %s string-to-hash\n", argv[0]); - exit (1); - } - for (j = 1; j < argc; ++j) - { - printf ("MD5 (\"%s\") = ", argv[j]); - my_MD5Init (&context); - my_MD5Update (&context, argv[j], strlen (argv[j])); - my_MD5Final (checksum, &context); - for (i = 0; i < 16; i++) - { - printf ("%02x", (unsigned int) checksum[i]); - } - printf ("\n"); - } - return 0; -} -#endif /* TEST */ diff --git a/dep/mysqllite/mysys/mf_arr_appstr.c b/dep/mysqllite/mysys/mf_arr_appstr.c deleted file mode 100644 index 1edbea9df4a..00000000000 --- a/dep/mysqllite/mysys/mf_arr_appstr.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2007 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 <m_string.h> /* strcmp() */ - - -/** - Append str to array, or move to the end if it already exists - - @param str String to be appended - @param array The array, terminated by a NULL element, all unused elements - pre-initialized to NULL - @param size Size of the array; array must be terminated by a NULL - pointer, so can hold size - 1 elements - - @retval FALSE Success - @retval TRUE Failure, array is full -*/ - -my_bool array_append_string_unique(const char *str, - const char **array, size_t size) -{ - const char **p; - /* end points at the terminating NULL element */ - const char **end= array + size - 1; - DBUG_ASSERT(*end == NULL); - - for (p= array; *p; ++p) - { - if (strcmp(*p, str) == 0) - break; - } - if (p >= end) - return TRUE; /* Array is full */ - - DBUG_ASSERT(*p == NULL || strcmp(*p, str) == 0); - - while (*(p + 1)) - { - *p= *(p + 1); - ++p; - } - - DBUG_ASSERT(p < end); - *p= str; - - return FALSE; /* Success */ -} diff --git a/dep/mysqllite/mysys/mf_cache.c b/dep/mysqllite/mysys/mf_cache.c deleted file mode 100644 index 691532c0d80..00000000000 --- a/dep/mysqllite/mysys/mf_cache.c +++ /dev/null @@ -1,121 +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 */ - -/* Open a temporary file and cache it with io_cache. Delete it on close */ - -#include "mysys_priv.h" -#include <m_string.h> -#include "my_static.h" -#include "mysys_err.h" - - /* - Remove an open tempfile so that it doesn't survive - if we crash; If the operating system doesn't support - this, just remember the file name for later removal - */ - -static my_bool cache_remove_open_tmp(IO_CACHE *cache __attribute__((unused)), - const char *name) -{ -#if O_TEMPORARY == 0 -#if !defined(CANT_DELETE_OPEN_FILES) - /* The following should always succeed */ - (void) my_delete(name,MYF(MY_WME | ME_NOINPUT)); -#else - int length; - if (!(cache->file_name= - (char*) my_malloc((length=strlen(name)+1),MYF(MY_WME)))) - { - my_close(cache->file,MYF(0)); - cache->file = -1; - errno=my_errno=ENOMEM; - return 1; - } - memcpy(cache->file_name,name,length); -#endif -#endif /* O_TEMPORARY == 0 */ - return 0; -} - - /* - ** Open tempfile cached by IO_CACHE - ** Should be used when no seeks are done (only reinit_io_buff) - ** Return 0 if cache is inited ok - ** The actual file is created when the IO_CACHE buffer gets filled - ** If dir is not given, use TMPDIR. - */ - -my_bool open_cached_file(IO_CACHE *cache, const char* dir, const char *prefix, - size_t cache_size, myf cache_myflags) -{ - DBUG_ENTER("open_cached_file"); - cache->dir= dir ? my_strdup(dir,MYF(cache_myflags & MY_WME)) : (char*) 0; - cache->prefix= (prefix ? my_strdup(prefix,MYF(cache_myflags & MY_WME)) : - (char*) 0); - cache->file_name=0; - cache->buffer=0; /* Mark that not open */ - if (!init_io_cache(cache,-1,cache_size,WRITE_CACHE,0L,0, - MYF(cache_myflags | MY_NABP))) - { - DBUG_RETURN(0); - } - my_free(cache->dir); - my_free(cache->prefix); - DBUG_RETURN(1); -} - - /* Create the temporary file */ - -my_bool real_open_cached_file(IO_CACHE *cache) -{ - char name_buff[FN_REFLEN]; - int error=1; - DBUG_ENTER("real_open_cached_file"); - if ((cache->file=create_temp_file(name_buff, cache->dir, cache->prefix, - (O_RDWR | O_BINARY | O_TRUNC | - O_TEMPORARY | O_SHORT_LIVED), - MYF(MY_WME))) >= 0) - { - error=0; - cache_remove_open_tmp(cache, name_buff); - } - DBUG_RETURN(error); -} - - -void close_cached_file(IO_CACHE *cache) -{ - DBUG_ENTER("close_cached_file"); - if (my_b_inited(cache)) - { - File file=cache->file; - cache->file= -1; /* Don't flush data */ - (void) end_io_cache(cache); - if (file >= 0) - { - (void) my_close(file,MYF(0)); -#ifdef CANT_DELETE_OPEN_FILES - if (cache->file_name) - { - (void) my_delete(cache->file_name,MYF(MY_WME | ME_NOINPUT)); - my_free(cache->file_name); - } -#endif - } - my_free(cache->dir); - my_free(cache->prefix); - } - DBUG_VOID_RETURN; -} diff --git a/dep/mysqllite/mysys/mf_dirname.c b/dep/mysqllite/mysys/mf_dirname.c deleted file mode 100644 index 5a9440483e4..00000000000 --- a/dep/mysqllite/mysys/mf_dirname.c +++ /dev/null @@ -1,154 +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 <m_string.h> - - /* Functions definied in this file */ - -size_t dirname_length(const char *name) -{ - register char *pos, *gpos; -#ifdef BASKSLASH_MBTAIL - CHARSET_INFO *fs= fs_character_set(); -#endif -#ifdef FN_DEVCHAR - if ((pos=(char*)strrchr(name,FN_DEVCHAR)) == 0) -#endif - pos=(char*) name-1; - - gpos= pos++; - for ( ; *pos ; pos++) /* Find last FN_LIBCHAR */ - { -#ifdef BASKSLASH_MBTAIL - uint l; - if (use_mb(fs) && (l= my_ismbchar(fs, pos, pos + 3))) - { - pos+= l - 1; - continue; - } -#endif - if (*pos == FN_LIBCHAR || *pos == '/') - gpos=pos; - } - return (size_t) (gpos+1-(char*) name); -} - - -/* - Gives directory part of filename. Directory ends with '/' - - SYNOPSIS - dirname_part() - to Store directory name here - name Original name - to_length Store length of 'to' here - - RETURN - # Length of directory part in 'name' -*/ - -size_t dirname_part(char *to, const char *name, size_t *to_res_length) -{ - size_t length; - DBUG_ENTER("dirname_part"); - DBUG_PRINT("enter",("'%s'",name)); - - length=dirname_length(name); - *to_res_length= (size_t) (convert_dirname(to, name, name+length) - to); - DBUG_RETURN(length); -} /* dirname */ - - -/* - Convert directory name to use under this system - - SYNPOSIS - convert_dirname() - 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. May be == to - from_end Pointer at end of filename (normally end \0) - - IMPLEMENTATION - If Windows converts '/' to '\' - Adds a FN_LIBCHAR to end if the result string if there isn't one - and the last isn't dev_char. - Copies data from 'from' until ASCII(0) for until from == from_end - If you want to use the whole 'from' string, just send NullS as the - last argument. - - If the result string is larger than FN_REFLEN -1, then it's cut. - - RETURN - Returns pointer to end \0 in to -*/ - -#ifndef FN_DEVCHAR -#define FN_DEVCHAR '\0' /* For easier code */ -#endif - -char *convert_dirname(char *to, const char *from, const char *from_end) -{ - char *to_org=to; -#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) - from_end=from+FN_REFLEN -2; - -#if FN_LIBCHAR != '/' - { - for (; from != from_end && *from ; from++) - { - if (*from == '/') - *to++= FN_LIBCHAR; - else - { -#ifdef BACKSLASH_MBTAIL - uint l; - if (use_mb(fs) && (l= my_ismbchar(fs, from, from + 3))) - { - memmove(to, from, l); - to+= l; - from+= l - 1; - to_org= to; /* Don't look inside mbchar */ - } - else -#endif - { - *to++= *from; - } - } - } - *to=0; - } -#else - /* This is ok even if to == from, becasue we need to cut the string */ - to= strmake(to, from, (size_t) (from_end-from)); -#endif - - /* Add FN_LIBCHAR to the end of directory path */ - if (to != to_org && (to[-1] != FN_LIBCHAR && to[-1] != FN_DEVCHAR)) - { - *to++=FN_LIBCHAR; - *to=0; - } - DBUG_RETURN(to); /* Pointer to end of dir */ -} /* convert_dirname */ diff --git a/dep/mysqllite/mysys/mf_fn_ext.c b/dep/mysqllite/mysys/mf_fn_ext.c deleted file mode 100644 index c872f2993c4..00000000000 --- a/dep/mysqllite/mysys/mf_fn_ext.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 <m_string.h> - -/* - Return a pointer to the extension of the filename. - - SYNOPSIS - fn_ext() - name Name of file - - DESCRIPTION - The extension is defined as everything after the first extension character - (normally '.') after the directory name. - - RETURN VALUES - Pointer to to the extension character. If there isn't any extension, - points at the end ASCII(0) of the filename. -*/ - -char *fn_ext(const char *name) -{ - register const char *pos, *gpos; - DBUG_ENTER("fn_ext"); - DBUG_PRINT("mfunkt",("name: '%s'",name)); - -#if defined(FN_DEVCHAR) || defined(BASKSLASH_MBTAIL) - { - char buff[FN_REFLEN]; - size_t res_length; - gpos= name+ dirname_part(buff,(char*) name, &res_length); - } -#else - if (!(gpos= strrchr(name, FN_LIBCHAR))) - gpos= name; -#endif - pos=strchr(gpos,FN_EXTCHAR); - DBUG_RETURN((char*) (pos ? pos : strend(gpos))); -} /* fn_ext */ diff --git a/dep/mysqllite/mysys/mf_format.c b/dep/mysqllite/mysys/mf_format.c deleted file mode 100644 index 6afa2938fa3..00000000000 --- a/dep/mysqllite/mysys/mf_format.c +++ /dev/null @@ -1,142 +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 <m_string.h> - -/* - Formats a filename with possible replace of directory of extension - Function can handle the case where 'to' == 'name' - For a description of the flag values, consult my_sys.h - The arguments should be in unix format. -*/ - -char * fn_format(char * to, const char *name, const char *dir, - const char *extension, uint flag) -{ - char dev[FN_REFLEN], buff[FN_REFLEN], *pos, *startpos; - const char *ext; - reg1 size_t length; - size_t dev_length; - DBUG_ENTER("fn_format"); - DBUG_PRINT("enter",("name: %s dir: %s extension: %s flag: %d", - name,dir,extension,flag)); - - /* Copy and skip directory */ - name+=(length=dirname_part(dev, (startpos=(char *) name), &dev_length)); - if (length == 0 || (flag & MY_REPLACE_DIR)) - { - /* Use given directory */ - convert_dirname(dev,dir,NullS); /* Fix to this OS */ - } - else if ((flag & MY_RELATIVE_PATH) && !test_if_hard_path(dev)) - { - /* Put 'dir' before the given path */ - strmake(buff,dev,sizeof(buff)-1); - pos=convert_dirname(dev,dir,NullS); - strmake(pos,buff,sizeof(buff)-1- (int) (pos-dev)); - } - - if (flag & MY_PACK_FILENAME) - pack_dirname(dev,dev); /* Put in ./.. and ~/.. */ - if (flag & MY_UNPACK_FILENAME) - (void) unpack_dirname(dev,dev); /* Replace ~/.. with dir */ - - if (!(flag & MY_APPEND_EXT) && - (pos= (char*) strchr(name,FN_EXTCHAR)) != NullS) - { - if ((flag & MY_REPLACE_EXT) == 0) /* If we should keep old ext */ - { - length=strlength(name); /* Use old extension */ - ext = ""; - } - else - { - length= (size_t) (pos-(char*) name); /* Change extension */ - ext= extension; - } - } - else - { - length=strlength(name); /* No ext, use the now one */ - ext=extension; - } - - if (strlen(dev)+length+strlen(ext) >= FN_REFLEN || length >= FN_LEN ) - { - /* To long path, return original or NULL */ - size_t tmp_length; - if (flag & MY_SAFE_PATH) - DBUG_RETURN(NullS); - tmp_length= strlength(startpos); - DBUG_PRINT("error",("dev: '%s' ext: '%s' length: %u",dev,ext, - (uint) length)); - (void) strmake(to,startpos,min(tmp_length,FN_REFLEN-1)); - } - else - { - if (to == startpos) - { - bmove(buff,(uchar*) name,length); /* Save name for last copy */ - name=buff; - } - pos=strmake(strmov(to,dev),name,length); - (void) strmov(pos,ext); /* Don't convert extension */ - } - /* - If MY_RETURN_REAL_PATH and MY_RESOLVE_SYMLINK is given, only do - realpath if the file is a symbolic link - */ - if (flag & MY_RETURN_REAL_PATH) - (void) my_realpath(to, to, MYF(flag & MY_RESOLVE_SYMLINKS ? - MY_RESOLVE_LINK: 0)); - else if (flag & MY_RESOLVE_SYMLINKS) - { - strmov(buff,to); - (void) my_readlink(to, buff, MYF(0)); - } - DBUG_RETURN(to); -} /* fn_format */ - - -/* - strlength(const string str) - Return length of string with end-space:s not counted. -*/ - -size_t strlength(const char *str) -{ - reg1 const char * pos; - reg2 const char * found; - DBUG_ENTER("strlength"); - - pos= found= str; - - while (*pos) - { - if (*pos != ' ') - { - while (*++pos && *pos != ' ') {}; - if (!*pos) - { - found=pos; /* String ends here */ - break; - } - } - found=pos; - while (*++pos == ' ') {}; - } - DBUG_RETURN((size_t) (found - str)); -} /* strlength */ diff --git a/dep/mysqllite/mysys/mf_getdate.c b/dep/mysqllite/mysys/mf_getdate.c deleted file mode 100644 index 9475bebd107..00000000000 --- a/dep/mysqllite/mysys/mf_getdate.c +++ /dev/null @@ -1,81 +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 */ - -/* Get date in a printable form: yyyy-mm-dd hh:mm:ss */ - -#include "mysys_priv.h" -#include <m_string.h> - -/* - get date as string - - SYNOPSIS - get_date() - to - string where date will be written - flag - format of date: - If flag & GETDATE_TIME Return date and time - If flag & GETDATE_SHORT_DATE Return short date format YYMMDD - If flag & GETDATE_HHMMSSTIME Return time in HHMMDD format. - If flag & GETDATE_GMT Date/time in GMT - If flag & GETDATE_FIXEDLENGTH Return fixed length date/time - date - for conversion -*/ - - -void get_date(register char * to, int flag, time_t date) -{ - reg2 struct tm *start_time; - time_t skr; -#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) - struct tm tm_tmp; -#endif - - skr=date ? (time_t) date : my_time(0); -#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT) - if (flag & GETDATE_GMT) - gmtime_r(&skr,&tm_tmp); - else - localtime_r(&skr,&tm_tmp); - start_time= &tm_tmp; -#else - if (flag & GETDATE_GMT) - start_time= gmtime(&skr); - else - start_time= localtime(&skr); -#endif - if (flag & GETDATE_SHORT_DATE) - sprintf(to,"%02d%02d%02d", - start_time->tm_year % 100, - start_time->tm_mon+1, - start_time->tm_mday); - else - sprintf(to, ((flag & GETDATE_FIXEDLENGTH) ? - "%4d-%02d-%02d" : "%d-%02d-%02d"), - start_time->tm_year+1900, - start_time->tm_mon+1, - start_time->tm_mday); - if (flag & GETDATE_DATE_TIME) - sprintf(strend(to), - ((flag & GETDATE_FIXEDLENGTH) ? - " %02d:%02d:%02d" : " %2d:%02d:%02d"), - start_time->tm_hour, - start_time->tm_min, - start_time->tm_sec); - else if (flag & GETDATE_HHMMSSTIME) - sprintf(strend(to),"%02d%02d%02d", - start_time->tm_hour, - start_time->tm_min, - start_time->tm_sec); -} /* get_date */ diff --git a/dep/mysqllite/mysys/mf_iocache.c b/dep/mysqllite/mysys/mf_iocache.c deleted file mode 100644 index 62e51ffb629..00000000000 --- a/dep/mysqllite/mysys/mf_iocache.c +++ /dev/null @@ -1,1949 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* - Cashing of files with only does (sequential) read or writes of fixed- - length records. A read isn't allowed to go over file-length. A read is ok - if it ends at file-length and next read can try to read after file-length - (and get a EOF-error). - Possibly use of asyncronic io. - macros for read and writes for faster io. - Used instead of FILE when reading or writing whole files. - This code makes mf_rec_cache obsolete (currently only used by ISAM) - One can change info->pos_in_file to a higher value to skip bytes in file if - also info->read_pos is set to info->read_end. - If called through open_cached_file(), then the temporary file will - only be created if a write exeeds the file buffer or if one calls - my_b_flush_io_cache(). - - If one uses SEQ_READ_APPEND, then two buffers are allocated, one for - reading and another for writing. Reads are first done from disk and - then done from the write buffer. This is an efficient way to read - from a log file when one is writing to it at the same time. - For this to work, the file has to be opened in append mode! - Note that when one uses SEQ_READ_APPEND, one MUST write using - my_b_append ! This is needed because we need to lock the mutex - every time we access the write buffer. - -TODO: - When one SEQ_READ_APPEND and we are reading and writing at the same time, - each time the write buffer gets full and it's written to disk, we will - always do a disk read to read a part of the buffer from disk to the - read buffer. - This should be fixed so that when we do a my_b_flush_io_cache() and - we have been reading the write buffer, we should transfer the rest of the - write buffer to the read buffer before we start to reuse it. -*/ - -#include "mysys_priv.h" -#include <m_string.h> -#ifdef HAVE_AIOWAIT -#include "mysys_err.h" -static void my_aiowait(my_aio_result *result); -#endif -#include <errno.h> - -#define lock_append_buffer(info) \ - mysql_mutex_lock(&(info)->append_buffer_lock) -#define unlock_append_buffer(info) \ - mysql_mutex_unlock(&(info)->append_buffer_lock) - -#define IO_ROUND_UP(X) (((X)+IO_SIZE-1) & ~(IO_SIZE-1)) -#define IO_ROUND_DN(X) ( (X) & ~(IO_SIZE-1)) - -/* - Setup internal pointers inside IO_CACHE - - SYNOPSIS - setup_io_cache() - info IO_CACHE handler - - NOTES - This is called on automaticly on init or reinit of IO_CACHE - It must be called externally if one moves or copies an IO_CACHE - object. -*/ - -void setup_io_cache(IO_CACHE* info) -{ - /* Ensure that my_b_tell() and my_b_bytes_in_cache works */ - if (info->type == WRITE_CACHE) - { - info->current_pos= &info->write_pos; - info->current_end= &info->write_end; - } - else - { - info->current_pos= &info->read_pos; - info->current_end= &info->read_end; - } -} - - -static void -init_functions(IO_CACHE* info) -{ - enum cache_type type= info->type; - switch (type) { - case READ_NET: - /* - Must be initialized by the caller. The problem is that - _my_b_net_read has to be defined in sql directory because of - the dependency on THD, and therefore cannot be visible to - programs that link against mysys but know nothing about THD, such - as myisamchk - */ - break; - case SEQ_READ_APPEND: - info->read_function = _my_b_seq_read; - info->write_function = 0; /* Force a core if used */ - break; - default: - info->read_function = info->share ? _my_b_read_r : _my_b_read; - info->write_function = _my_b_write; - } - - setup_io_cache(info); -} - - -/* - Initialize an IO_CACHE object - - SYNOPSOS - init_io_cache() - info cache handler to initialize - file File that should be associated to to the handler - If == -1 then real_open_cached_file() - will be called when it's time to open file. - cachesize Size of buffer to allocate for read/write - If == 0 then use my_default_record_cache_size - type Type of cache - seek_offset Where cache should start reading/writing - use_async_io Set to 1 of we should use async_io (if avaiable) - cache_myflags Bitmap of differnt flags - MY_WME | MY_FAE | MY_NABP | MY_FNABP | - MY_DONT_CHECK_FILESIZE - - RETURN - 0 ok - # error -*/ - -int init_io_cache(IO_CACHE *info, File file, size_t cachesize, - enum cache_type type, my_off_t seek_offset, - pbool use_async_io, myf cache_myflags) -{ - size_t min_cache; - my_off_t pos; - my_off_t end_of_file= ~(my_off_t) 0; - DBUG_ENTER("init_io_cache"); - DBUG_PRINT("enter",("cache: 0x%lx type: %d pos: %ld", - (ulong) info, (int) type, (ulong) seek_offset)); - - info->file= file; - info->type= TYPE_NOT_SET; /* Don't set it until mutex are created */ - info->pos_in_file= seek_offset; - info->pre_close = info->pre_read = info->post_read = 0; - info->arg = 0; - info->alloced_buffer = 0; - info->buffer=0; - info->seek_not_done= 0; - - if (file >= 0) - { - pos= mysql_file_tell(file, MYF(0)); - if ((pos == (my_off_t) -1) && (my_errno == ESPIPE)) - { - /* - This kind of object doesn't support seek() or tell(). Don't set a - flag that will make us again try to seek() later and fail. - */ - info->seek_not_done= 0; - /* - Additionally, if we're supposed to start somewhere other than the - the beginning of whatever this file is, then somebody made a bad - assumption. - */ - DBUG_ASSERT(seek_offset == 0); - } - else - info->seek_not_done= test(seek_offset != pos); - } - - info->disk_writes= 0; - info->share=0; - - if (!cachesize && !(cachesize= my_default_record_cache_size)) - DBUG_RETURN(1); /* No cache requested */ - min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2; - if (type == READ_CACHE || type == SEQ_READ_APPEND) - { /* Assume file isn't growing */ - if (!(cache_myflags & MY_DONT_CHECK_FILESIZE)) - { - /* Calculate end of file to avoid allocating oversized buffers */ - end_of_file= mysql_file_seek(file, 0L, MY_SEEK_END, MYF(0)); - /* Need to reset seek_not_done now that we just did a seek. */ - info->seek_not_done= end_of_file == seek_offset ? 0 : 1; - if (end_of_file < seek_offset) - end_of_file=seek_offset; - /* Trim cache size if the file is very small */ - if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1) - { - cachesize= (size_t) (end_of_file-seek_offset)+IO_SIZE*2-1; - use_async_io=0; /* No need to use async */ - } - } - } - cache_myflags &= ~MY_DONT_CHECK_FILESIZE; - if (type != READ_NET && type != WRITE_NET) - { - /* Retry allocating memory in smaller blocks until we get one */ - cachesize= ((cachesize + min_cache-1) & ~(min_cache-1)); - for (;;) - { - size_t buffer_block; - /* - Unset MY_WAIT_IF_FULL bit if it is set, to prevent conflict with - MY_ZEROFILL. - */ - myf flags= (myf) (cache_myflags & ~(MY_WME | MY_WAIT_IF_FULL)); - - if (cachesize < min_cache) - cachesize = min_cache; - buffer_block= cachesize; - if (type == SEQ_READ_APPEND) - buffer_block *= 2; - if (cachesize == min_cache) - flags|= (myf) MY_WME; - - if ((info->buffer= (uchar*) my_malloc(buffer_block, flags)) != 0) - { - info->write_buffer=info->buffer; - if (type == SEQ_READ_APPEND) - info->write_buffer = info->buffer + cachesize; - info->alloced_buffer=1; - break; /* Enough memory found */ - } - if (cachesize == min_cache) - DBUG_RETURN(2); /* Can't alloc cache */ - /* Try with less memory */ - cachesize= (cachesize*3/4 & ~(min_cache-1)); - } - } - - DBUG_PRINT("info",("init_io_cache: cachesize = %lu", (ulong) cachesize)); - info->read_length=info->buffer_length=cachesize; - info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP); - info->request_pos= info->read_pos= info->write_pos = info->buffer; - if (type == SEQ_READ_APPEND) - { - info->append_read_pos = info->write_pos = info->write_buffer; - info->write_end = info->write_buffer + info->buffer_length; - mysql_mutex_init(key_IO_CACHE_append_buffer_lock, - &info->append_buffer_lock, MY_MUTEX_INIT_FAST); - } -#if defined(SAFE_MUTEX) - else - { - /* Clear mutex so that safe_mutex will notice that it's not initialized */ - bzero((char*) &info->append_buffer_lock, sizeof(info)); - } -#endif - - if (type == WRITE_CACHE) - info->write_end= - info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1)); - else - info->read_end=info->buffer; /* Nothing in cache */ - - /* End_of_file may be changed by user later */ - info->end_of_file= end_of_file; - info->error=0; - info->type= type; - init_functions(info); -#ifdef HAVE_AIOWAIT - if (use_async_io && ! my_disable_async_io) - { - DBUG_PRINT("info",("Using async io")); - info->read_length/=2; - info->read_function=_my_b_async_read; - } - info->inited=info->aio_result.pending=0; -#endif - DBUG_RETURN(0); -} /* init_io_cache */ - - /* Wait until current request is ready */ - -#ifdef HAVE_AIOWAIT -static void my_aiowait(my_aio_result *result) -{ - if (result->pending) - { - struct aio_result_t *tmp; - for (;;) - { - if ((int) (tmp=aiowait((struct timeval *) 0)) == -1) - { - if (errno == EINTR) - continue; - DBUG_PRINT("error",("No aio request, error: %d",errno)); - result->pending=0; /* Assume everythings is ok */ - break; - } - ((my_aio_result*) tmp)->pending=0; - if ((my_aio_result*) tmp == result) - break; - } - } - return; -} -#endif - - -/* - Use this to reset cache to re-start reading or to change the type - between READ_CACHE <-> WRITE_CACHE - If we are doing a reinit of a cache where we have the start of the file - in the cache, we are reusing this memory without flushing it to disk. -*/ - -my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type, - my_off_t seek_offset, - pbool use_async_io __attribute__((unused)), - pbool clear_cache) -{ - DBUG_ENTER("reinit_io_cache"); - DBUG_PRINT("enter",("cache: 0x%lx type: %d seek_offset: %lu clear_cache: %d", - (ulong) info, type, (ulong) seek_offset, - (int) clear_cache)); - - /* One can't do reinit with the following types */ - DBUG_ASSERT(type != READ_NET && info->type != READ_NET && - type != WRITE_NET && info->type != WRITE_NET && - type != SEQ_READ_APPEND && info->type != SEQ_READ_APPEND); - - /* If the whole file is in memory, avoid flushing to disk */ - if (! clear_cache && - seek_offset >= info->pos_in_file && - seek_offset <= my_b_tell(info)) - { - /* Reuse current buffer without flushing it to disk */ - uchar *pos; - if (info->type == WRITE_CACHE && type == READ_CACHE) - { - info->read_end=info->write_pos; - info->end_of_file=my_b_tell(info); - /* - Trigger a new seek only if we have a valid - file handle. - */ - info->seek_not_done= (info->file != -1); - } - else if (type == WRITE_CACHE) - { - if (info->type == READ_CACHE) - { - info->write_end=info->write_buffer+info->buffer_length; - info->seek_not_done=1; - } - info->end_of_file = ~(my_off_t) 0; - } - pos=info->request_pos+(seek_offset-info->pos_in_file); - if (type == WRITE_CACHE) - info->write_pos=pos; - else - info->read_pos= pos; -#ifdef HAVE_AIOWAIT - my_aiowait(&info->aio_result); /* Wait for outstanding req */ -#endif - } - else - { - /* - If we change from WRITE_CACHE to READ_CACHE, assume that everything - after the current positions should be ignored - */ - if (info->type == WRITE_CACHE && type == READ_CACHE) - info->end_of_file=my_b_tell(info); - /* flush cache if we want to reuse it */ - if (!clear_cache && my_b_flush_io_cache(info,1)) - DBUG_RETURN(1); - info->pos_in_file=seek_offset; - /* Better to do always do a seek */ - info->seek_not_done=1; - info->request_pos=info->read_pos=info->write_pos=info->buffer; - if (type == READ_CACHE) - { - info->read_end=info->buffer; /* Nothing in cache */ - } - else - { - info->write_end=(info->buffer + info->buffer_length - - (seek_offset & (IO_SIZE-1))); - info->end_of_file= ~(my_off_t) 0; - } - } - info->type=type; - info->error=0; - init_functions(info); - -#ifdef HAVE_AIOWAIT - if (use_async_io && ! my_disable_async_io && - ((ulong) info->buffer_length < - (ulong) (info->end_of_file - seek_offset))) - { - info->read_length=info->buffer_length/2; - info->read_function=_my_b_async_read; - } - info->inited=0; -#endif - DBUG_RETURN(0); -} /* reinit_io_cache */ - - - -/* - Read buffered. - - SYNOPSIS - _my_b_read() - info IO_CACHE pointer - Buffer Buffer to retrieve count bytes from file - Count Number of bytes to read into Buffer - - NOTE - This function is only called from the my_b_read() macro when there - isn't enough characters in the buffer to satisfy the request. - - WARNING - - When changing this function, be careful with handling file offsets - (end-of_file, pos_in_file). Do not cast them to possibly smaller - types than my_off_t unless you can be sure that their value fits. - Same applies to differences of file offsets. - - When changing this function, check _my_b_read_r(). It might need the - same change. - - RETURN - 0 we succeeded in reading all data - 1 Error: couldn't read requested characters. In this case: - If info->error == -1, we got a read error. - Otherwise info->error contains the number of bytes in Buffer. -*/ - -int _my_b_read(register IO_CACHE *info, uchar *Buffer, size_t Count) -{ - size_t length,diff_length,left_length, max_length; - my_off_t pos_in_file; - DBUG_ENTER("_my_b_read"); - - /* If the buffer is not empty yet, copy what is available. */ - if ((left_length= (size_t) (info->read_end-info->read_pos))) - { - DBUG_ASSERT(Count >= left_length); /* User is not using my_b_read() */ - memcpy(Buffer,info->read_pos, left_length); - Buffer+=left_length; - Count-=left_length; - } - - /* pos_in_file always point on where info->buffer was read */ - pos_in_file=info->pos_in_file+ (size_t) (info->read_end - info->buffer); - - /* - Whenever a function which operates on IO_CACHE flushes/writes - some part of the IO_CACHE to disk it will set the property - "seek_not_done" to indicate this to other functions operating - on the IO_CACHE. - */ - if (info->seek_not_done) - { - if ((mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) - != MY_FILEPOS_ERROR)) - { - /* No error, reset seek_not_done flag. */ - info->seek_not_done= 0; - } - else - { - /* - If the seek failed and the error number is ESPIPE, it is because - info->file is a pipe or socket or FIFO. We never should have tried - to seek on that. See Bugs#25807 and #22828 for more info. - */ - DBUG_ASSERT(my_errno != ESPIPE); - info->error= -1; - DBUG_RETURN(1); - } - } - - /* - Calculate, how much we are within a IO_SIZE block. Ideally this - should be zero. - */ - diff_length= (size_t) (pos_in_file & (IO_SIZE-1)); - - /* - If more than a block plus the rest of the current block is wanted, - we do read directly, without filling the buffer. - */ - if (Count >= (size_t) (IO_SIZE+(IO_SIZE-diff_length))) - { /* Fill first intern buffer */ - size_t read_length; - if (info->end_of_file <= pos_in_file) - { - /* End of file. Return, what we did copy from the buffer. */ - info->error= (int) left_length; - DBUG_RETURN(1); - } - /* - Crop the wanted count to a multiple of IO_SIZE and subtract, - what we did already read from a block. That way, the read will - end aligned with a block. - */ - length=(Count & (size_t) ~(IO_SIZE-1))-diff_length; - if ((read_length= mysql_file_read(info->file,Buffer, length, info->myflags)) - != length) - { - /* - If we didn't get, what we wanted, we either return -1 for a read - error, or (it's end of file), how much we got in total. - */ - info->error= (read_length == (size_t) -1 ? -1 : - (int) (read_length+left_length)); - DBUG_RETURN(1); - } - Count-=length; - Buffer+=length; - pos_in_file+=length; - left_length+=length; - diff_length=0; - } - - /* - At this point, we want less than one and a partial block. - We will read a full cache, minus the number of bytes, we are - within a block already. So we will reach new alignment. - */ - max_length= info->read_length-diff_length; - /* We will not read past end of file. */ - if (info->type != READ_FIFO && - max_length > (info->end_of_file - pos_in_file)) - max_length= (size_t) (info->end_of_file - pos_in_file); - /* - If there is nothing left to read, - we either are done, or we failed to fulfill the request. - Otherwise, we read max_length into the cache. - */ - if (!max_length) - { - if (Count) - { - /* We couldn't fulfil the request. Return, how much we got. */ - info->error= left_length; - DBUG_RETURN(1); - } - length=0; /* Didn't read any chars */ - } - else if ((length= mysql_file_read(info->file,info->buffer, max_length, - info->myflags)) < Count || - length == (size_t) -1) - { - /* - We got an read error, or less than requested (end of file). - If not a read error, copy, what we got. - */ - if (length != (size_t) -1) - memcpy(Buffer, info->buffer, length); - info->pos_in_file= pos_in_file; - /* For a read error, return -1, otherwise, what we got in total. */ - info->error= length == (size_t) -1 ? -1 : (int) (length+left_length); - info->read_pos=info->read_end=info->buffer; - DBUG_RETURN(1); - } - /* - Count is the remaining number of bytes requested. - length is the amount of data in the cache. - Read Count bytes from the cache. - */ - info->read_pos=info->buffer+Count; - info->read_end=info->buffer+length; - info->pos_in_file=pos_in_file; - memcpy(Buffer, info->buffer, Count); - DBUG_RETURN(0); -} - - -/* - Prepare IO_CACHE for shared use. - - SYNOPSIS - init_io_cache_share() - read_cache A read cache. This will be copied for - every thread after setup. - cshare The share. - write_cache If non-NULL a write cache that is to be - synchronized with the read caches. - num_threads Number of threads sharing the cache - including the write thread if any. - - DESCRIPTION - - The shared cache is used so: One IO_CACHE is initialized with - init_io_cache(). This includes the allocation of a buffer. Then a - share is allocated and init_io_cache_share() is called with the io - cache and the share. Then the io cache is copied for each thread. So - every thread has its own copy of IO_CACHE. But the allocated buffer - is shared because cache->buffer is the same for all caches. - - One thread reads data from the file into the buffer. All threads - read from the buffer, but every thread maintains its own set of - pointers into the buffer. When all threads have used up the buffer - contents, one of the threads reads the next block of data into the - buffer. To accomplish this, each thread enters the cache lock before - accessing the buffer. They wait in lock_io_cache() until all threads - joined the lock. The last thread entering the lock is in charge of - reading from file to buffer. It wakes all threads when done. - - Synchronizing a write cache to the read caches works so: Whenever - the write buffer needs a flush, the write thread enters the lock and - waits for all other threads to enter the lock too. They do this when - they have used up the read buffer. When all threads are in the lock, - the write thread copies the write buffer to the read buffer and - wakes all threads. - - share->running_threads is the number of threads not being in the - cache lock. When entering lock_io_cache() the number is decreased. - When the thread that fills the buffer enters unlock_io_cache() the - number is reset to the number of threads. The condition - running_threads == 0 means that all threads are in the lock. Bumping - up the number to the full count is non-intuitive. But increasing the - number by one for each thread that leaves the lock could lead to a - solo run of one thread. The last thread to join a lock reads from - file to buffer, wakes the other threads, processes the data in the - cache and enters the lock again. If no other thread left the lock - meanwhile, it would think it's the last one again and read the next - block... - - The share has copies of 'error', 'buffer', 'read_end', and - 'pos_in_file' from the thread that filled the buffer. We may not be - able to access this information directly from its cache because the - thread may be removed from the share before the variables could be - copied by all other threads. Or, if a write buffer is synchronized, - it would change its 'pos_in_file' after waking the other threads, - possibly before they could copy its value. - - However, the 'buffer' variable in the share is for a synchronized - write cache. It needs to know where to put the data. Otherwise it - would need access to the read cache of one of the threads that is - not yet removed from the share. - - RETURN - void -*/ - -void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare, - IO_CACHE *write_cache, uint num_threads) -{ - DBUG_ENTER("init_io_cache_share"); - DBUG_PRINT("io_cache_share", ("read_cache: 0x%lx share: 0x%lx " - "write_cache: 0x%lx threads: %u", - (long) read_cache, (long) cshare, - (long) write_cache, num_threads)); - - DBUG_ASSERT(num_threads > 1); - DBUG_ASSERT(read_cache->type == READ_CACHE); - DBUG_ASSERT(!write_cache || (write_cache->type == WRITE_CACHE)); - - mysql_mutex_init(key_IO_CACHE_SHARE_mutex, - &cshare->mutex, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_IO_CACHE_SHARE_cond, &cshare->cond, 0); - mysql_cond_init(key_IO_CACHE_SHARE_cond_writer, &cshare->cond_writer, 0); - - cshare->running_threads= num_threads; - cshare->total_threads= num_threads; - cshare->error= 0; /* Initialize. */ - cshare->buffer= read_cache->buffer; - cshare->read_end= NULL; /* See function comment of lock_io_cache(). */ - cshare->pos_in_file= 0; /* See function comment of lock_io_cache(). */ - cshare->source_cache= write_cache; /* Can be NULL. */ - - read_cache->share= cshare; - read_cache->read_function= _my_b_read_r; - read_cache->current_pos= NULL; - read_cache->current_end= NULL; - - if (write_cache) - write_cache->share= cshare; - - DBUG_VOID_RETURN; -} - - -/* - Remove a thread from shared access to IO_CACHE. - - SYNOPSIS - remove_io_thread() - cache The IO_CACHE to be removed from the share. - - NOTE - - Every thread must do that on exit for not to deadlock other threads. - - The last thread destroys the pthread resources. - - A writer flushes its cache first. - - RETURN - void -*/ - -void remove_io_thread(IO_CACHE *cache) -{ - IO_CACHE_SHARE *cshare= cache->share; - uint total; - DBUG_ENTER("remove_io_thread"); - - /* If the writer goes, it needs to flush the write cache. */ - if (cache == cshare->source_cache) - flush_io_cache(cache); - - mysql_mutex_lock(&cshare->mutex); - DBUG_PRINT("io_cache_share", ("%s: 0x%lx", - (cache == cshare->source_cache) ? - "writer" : "reader", (long) cache)); - - /* Remove from share. */ - total= --cshare->total_threads; - DBUG_PRINT("io_cache_share", ("remaining threads: %u", total)); - - /* Detach from share. */ - cache->share= NULL; - - /* If the writer goes, let the readers know. */ - if (cache == cshare->source_cache) - { - DBUG_PRINT("io_cache_share", ("writer leaves")); - cshare->source_cache= NULL; - } - - /* If all threads are waiting for me to join the lock, wake them. */ - if (!--cshare->running_threads) - { - DBUG_PRINT("io_cache_share", ("the last running thread leaves, wake all")); - mysql_cond_signal(&cshare->cond_writer); - mysql_cond_broadcast(&cshare->cond); - } - - mysql_mutex_unlock(&cshare->mutex); - - if (!total) - { - DBUG_PRINT("io_cache_share", ("last thread removed, destroy share")); - mysql_cond_destroy (&cshare->cond_writer); - mysql_cond_destroy (&cshare->cond); - mysql_mutex_destroy(&cshare->mutex); - } - - DBUG_VOID_RETURN; -} - - -/* - Lock IO cache and wait for all other threads to join. - - SYNOPSIS - lock_io_cache() - cache The cache of the thread entering the lock. - pos File position of the block to read. - Unused for the write thread. - - DESCRIPTION - - Wait for all threads to finish with the current buffer. We want - all threads to proceed in concert. The last thread to join - lock_io_cache() will read the block from file and all threads start - to use it. Then they will join again for reading the next block. - - The waiting threads detect a fresh buffer by comparing - cshare->pos_in_file with the position they want to process next. - Since the first block may start at position 0, we take - cshare->read_end as an additional condition. This variable is - initialized to NULL and will be set after a block of data is written - to the buffer. - - RETURN - 1 OK, lock in place, go ahead and read. - 0 OK, unlocked, another thread did the read. -*/ - -static int lock_io_cache(IO_CACHE *cache, my_off_t pos) -{ - IO_CACHE_SHARE *cshare= cache->share; - DBUG_ENTER("lock_io_cache"); - - /* Enter the lock. */ - mysql_mutex_lock(&cshare->mutex); - cshare->running_threads--; - DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u", - (cache == cshare->source_cache) ? - "writer" : "reader", (long) cache, (ulong) pos, - cshare->running_threads)); - - if (cshare->source_cache) - { - /* A write cache is synchronized to the read caches. */ - - if (cache == cshare->source_cache) - { - /* The writer waits until all readers are here. */ - while (cshare->running_threads) - { - DBUG_PRINT("io_cache_share", ("writer waits in lock")); - mysql_cond_wait(&cshare->cond_writer, &cshare->mutex); - } - DBUG_PRINT("io_cache_share", ("writer awoke, going to copy")); - - /* Stay locked. Leave the lock later by unlock_io_cache(). */ - DBUG_RETURN(1); - } - - /* The last thread wakes the writer. */ - if (!cshare->running_threads) - { - DBUG_PRINT("io_cache_share", ("waking writer")); - mysql_cond_signal(&cshare->cond_writer); - } - - /* - Readers wait until the data is copied from the writer. Another - reason to stop waiting is the removal of the write thread. If this - happens, we leave the lock with old data in the buffer. - */ - while ((!cshare->read_end || (cshare->pos_in_file < pos)) && - cshare->source_cache) - { - DBUG_PRINT("io_cache_share", ("reader waits in lock")); - mysql_cond_wait(&cshare->cond, &cshare->mutex); - } - - /* - If the writer was removed from the share while this thread was - asleep, we need to simulate an EOF condition. The writer cannot - reset the share variables as they might still be in use by readers - of the last block. When we awake here then because the last - joining thread signalled us. If the writer is not the last, it - will not signal. So it is safe to clear the buffer here. - */ - if (!cshare->read_end || (cshare->pos_in_file < pos)) - { - DBUG_PRINT("io_cache_share", ("reader found writer removed. EOF")); - cshare->read_end= cshare->buffer; /* Empty buffer. */ - cshare->error= 0; /* EOF is not an error. */ - } - } - else - { - /* - There are read caches only. The last thread arriving in - lock_io_cache() continues with a locked cache and reads the block. - */ - if (!cshare->running_threads) - { - DBUG_PRINT("io_cache_share", ("last thread joined, going to read")); - /* Stay locked. Leave the lock later by unlock_io_cache(). */ - DBUG_RETURN(1); - } - - /* - All other threads wait until the requested block is read by the - last thread arriving. Another reason to stop waiting is the - removal of a thread. If this leads to all threads being in the - lock, we have to continue also. The first of the awaken threads - will then do the read. - */ - while ((!cshare->read_end || (cshare->pos_in_file < pos)) && - cshare->running_threads) - { - DBUG_PRINT("io_cache_share", ("reader waits in lock")); - mysql_cond_wait(&cshare->cond, &cshare->mutex); - } - - /* If the block is not yet read, continue with a locked cache and read. */ - if (!cshare->read_end || (cshare->pos_in_file < pos)) - { - DBUG_PRINT("io_cache_share", ("reader awoke, going to read")); - /* Stay locked. Leave the lock later by unlock_io_cache(). */ - DBUG_RETURN(1); - } - - /* Another thread did read the block already. */ - } - DBUG_PRINT("io_cache_share", ("reader awoke, going to process %u bytes", - (uint) (cshare->read_end ? (size_t) - (cshare->read_end - cshare->buffer) : - 0))); - - /* - Leave the lock. Do not call unlock_io_cache() later. The thread that - filled the buffer did this and marked all threads as running. - */ - mysql_mutex_unlock(&cshare->mutex); - DBUG_RETURN(0); -} - - -/* - Unlock IO cache. - - SYNOPSIS - unlock_io_cache() - cache The cache of the thread leaving the lock. - - NOTE - This is called by the thread that filled the buffer. It marks all - threads as running and awakes them. This must not be done by any - other thread. - - Do not signal cond_writer. Either there is no writer or the writer - is the only one who can call this function. - - The reason for resetting running_threads to total_threads before - waking all other threads is that it could be possible that this - thread is so fast with processing the buffer that it enters the lock - before even one other thread has left it. If every awoken thread - would increase running_threads by one, this thread could think that - he is again the last to join and would not wait for the other - threads to process the data. - - RETURN - void -*/ - -static void unlock_io_cache(IO_CACHE *cache) -{ - IO_CACHE_SHARE *cshare= cache->share; - DBUG_ENTER("unlock_io_cache"); - DBUG_PRINT("io_cache_share", ("%s: 0x%lx pos: %lu running: %u", - (cache == cshare->source_cache) ? - "writer" : "reader", - (long) cache, (ulong) cshare->pos_in_file, - cshare->total_threads)); - - cshare->running_threads= cshare->total_threads; - mysql_cond_broadcast(&cshare->cond); - mysql_mutex_unlock(&cshare->mutex); - DBUG_VOID_RETURN; -} - - -/* - Read from IO_CACHE when it is shared between several threads. - - SYNOPSIS - _my_b_read_r() - cache IO_CACHE pointer - Buffer Buffer to retrieve count bytes from file - Count Number of bytes to read into Buffer - - NOTE - This function is only called from the my_b_read() macro when there - isn't enough characters in the buffer to satisfy the request. - - IMPLEMENTATION - - It works as follows: when a thread tries to read from a file (that - is, after using all the data from the (shared) buffer), it just - hangs on lock_io_cache(), waiting for other threads. When the very - last thread attempts a read, lock_io_cache() returns 1, the thread - does actual IO and unlock_io_cache(), which signals all the waiting - threads that data is in the buffer. - - WARNING - - When changing this function, be careful with handling file offsets - (end-of_file, pos_in_file). Do not cast them to possibly smaller - types than my_off_t unless you can be sure that their value fits. - Same applies to differences of file offsets. (Bug #11527) - - When changing this function, check _my_b_read(). It might need the - same change. - - RETURN - 0 we succeeded in reading all data - 1 Error: can't read requested characters -*/ - -int _my_b_read_r(register IO_CACHE *cache, uchar *Buffer, size_t Count) -{ - my_off_t pos_in_file; - size_t length, diff_length, left_length; - IO_CACHE_SHARE *cshare= cache->share; - DBUG_ENTER("_my_b_read_r"); - - if ((left_length= (size_t) (cache->read_end - cache->read_pos))) - { - DBUG_ASSERT(Count >= left_length); /* User is not using my_b_read() */ - memcpy(Buffer, cache->read_pos, left_length); - Buffer+= left_length; - Count-= left_length; - } - while (Count) - { - size_t cnt, len; - - pos_in_file= cache->pos_in_file + (cache->read_end - cache->buffer); - diff_length= (size_t) (pos_in_file & (IO_SIZE-1)); - length=IO_ROUND_UP(Count+diff_length)-diff_length; - length= ((length <= cache->read_length) ? - length + IO_ROUND_DN(cache->read_length - length) : - length - IO_ROUND_UP(length - cache->read_length)); - if (cache->type != READ_FIFO && - (length > (cache->end_of_file - pos_in_file))) - length= (size_t) (cache->end_of_file - pos_in_file); - if (length == 0) - { - cache->error= (int) left_length; - DBUG_RETURN(1); - } - if (lock_io_cache(cache, pos_in_file)) - { - /* With a synchronized write/read cache we won't come here... */ - DBUG_ASSERT(!cshare->source_cache); - /* - ... unless the writer has gone before this thread entered the - lock. Simulate EOF in this case. It can be distinguished by - cache->file. - */ - if (cache->file < 0) - len= 0; - else - { - /* - Whenever a function which operates on IO_CACHE flushes/writes - some part of the IO_CACHE to disk it will set the property - "seek_not_done" to indicate this to other functions operating - on the IO_CACHE. - */ - if (cache->seek_not_done) - { - if (mysql_file_seek(cache->file, pos_in_file, MY_SEEK_SET, MYF(0)) - == MY_FILEPOS_ERROR) - { - cache->error= -1; - unlock_io_cache(cache); - DBUG_RETURN(1); - } - } - len= mysql_file_read(cache->file, cache->buffer, length, cache->myflags); - } - DBUG_PRINT("io_cache_share", ("read %lu bytes", (ulong) len)); - - cache->read_end= cache->buffer + (len == (size_t) -1 ? 0 : len); - cache->error= (len == length ? 0 : (int) len); - cache->pos_in_file= pos_in_file; - - /* Copy important values to the share. */ - cshare->error= cache->error; - cshare->read_end= cache->read_end; - cshare->pos_in_file= pos_in_file; - - /* Mark all threads as running and wake them. */ - unlock_io_cache(cache); - } - else - { - /* - With a synchronized write/read cache readers always come here. - Copy important values from the share. - */ - cache->error= cshare->error; - cache->read_end= cshare->read_end; - cache->pos_in_file= cshare->pos_in_file; - - len= ((cache->error == -1) ? (size_t) -1 : - (size_t) (cache->read_end - cache->buffer)); - } - cache->read_pos= cache->buffer; - cache->seek_not_done= 0; - if (len == 0 || len == (size_t) -1) - { - DBUG_PRINT("io_cache_share", ("reader error. len %lu left %lu", - (ulong) len, (ulong) left_length)); - cache->error= (int) left_length; - DBUG_RETURN(1); - } - cnt= (len > Count) ? Count : len; - memcpy(Buffer, cache->read_pos, cnt); - Count -= cnt; - Buffer+= cnt; - left_length+= cnt; - cache->read_pos+= cnt; - } - DBUG_RETURN(0); -} - - -/* - Copy data from write cache to read cache. - - SYNOPSIS - copy_to_read_buffer() - write_cache The write cache. - write_buffer The source of data, mostly the cache buffer. - write_length The number of bytes to copy. - - NOTE - The write thread will wait for all read threads to join the cache - lock. Then it copies the data over and wakes the read threads. - - RETURN - void -*/ - -static void copy_to_read_buffer(IO_CACHE *write_cache, - const uchar *write_buffer, size_t write_length) -{ - IO_CACHE_SHARE *cshare= write_cache->share; - - DBUG_ASSERT(cshare->source_cache == write_cache); - /* - write_length is usually less or equal to buffer_length. - It can be bigger if _my_b_write() is called with a big length. - */ - while (write_length) - { - size_t copy_length= min(write_length, write_cache->buffer_length); - int __attribute__((unused)) rc; - - rc= lock_io_cache(write_cache, write_cache->pos_in_file); - /* The writing thread does always have the lock when it awakes. */ - DBUG_ASSERT(rc); - - memcpy(cshare->buffer, write_buffer, copy_length); - - cshare->error= 0; - cshare->read_end= cshare->buffer + copy_length; - cshare->pos_in_file= write_cache->pos_in_file; - - /* Mark all threads as running and wake them. */ - unlock_io_cache(write_cache); - - write_buffer+= copy_length; - write_length-= copy_length; - } -} - - -/* - Do sequential read from the SEQ_READ_APPEND cache. - - We do this in three stages: - - first read from info->buffer - - then if there are still data to read, try the file descriptor - - afterwards, if there are still data to read, try append buffer - - RETURNS - 0 Success - 1 Failed to read -*/ - -int _my_b_seq_read(register IO_CACHE *info, uchar *Buffer, size_t Count) -{ - size_t length, diff_length, left_length, save_count, max_length; - my_off_t pos_in_file; - save_count=Count; - - /* first, read the regular buffer */ - if ((left_length=(size_t) (info->read_end-info->read_pos))) - { - DBUG_ASSERT(Count > left_length); /* User is not using my_b_read() */ - memcpy(Buffer,info->read_pos, left_length); - Buffer+=left_length; - Count-=left_length; - } - lock_append_buffer(info); - - /* pos_in_file always point on where info->buffer was read */ - if ((pos_in_file=info->pos_in_file + - (size_t) (info->read_end - info->buffer)) >= info->end_of_file) - goto read_append_buffer; - - /* - With read-append cache we must always do a seek before we read, - because the write could have moved the file pointer astray - */ - if (mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) == MY_FILEPOS_ERROR) - { - info->error= -1; - unlock_append_buffer(info); - return (1); - } - info->seek_not_done=0; - - diff_length= (size_t) (pos_in_file & (IO_SIZE-1)); - - /* now the second stage begins - read from file descriptor */ - if (Count >= (size_t) (IO_SIZE+(IO_SIZE-diff_length))) - { - /* Fill first intern buffer */ - size_t read_length; - - length=(Count & (size_t) ~(IO_SIZE-1))-diff_length; - if ((read_length= mysql_file_read(info->file,Buffer, length, - info->myflags)) == (size_t) -1) - { - info->error= -1; - unlock_append_buffer(info); - return 1; - } - Count-=read_length; - Buffer+=read_length; - pos_in_file+=read_length; - - if (read_length != length) - { - /* - We only got part of data; Read the rest of the data from the - write buffer - */ - goto read_append_buffer; - } - left_length+=length; - diff_length=0; - } - - max_length= info->read_length-diff_length; - if (max_length > (info->end_of_file - pos_in_file)) - max_length= (size_t) (info->end_of_file - pos_in_file); - if (!max_length) - { - if (Count) - goto read_append_buffer; - length=0; /* Didn't read any more chars */ - } - else - { - length= mysql_file_read(info->file,info->buffer, max_length, info->myflags); - if (length == (size_t) -1) - { - info->error= -1; - unlock_append_buffer(info); - return 1; - } - if (length < Count) - { - memcpy(Buffer, info->buffer, length); - Count -= length; - Buffer += length; - - /* - added the line below to make - DBUG_ASSERT(pos_in_file==info->end_of_file) pass. - otherwise this does not appear to be needed - */ - pos_in_file += length; - goto read_append_buffer; - } - } - unlock_append_buffer(info); - info->read_pos=info->buffer+Count; - info->read_end=info->buffer+length; - info->pos_in_file=pos_in_file; - memcpy(Buffer,info->buffer,(size_t) Count); - return 0; - -read_append_buffer: - - /* - Read data from the current write buffer. - Count should never be == 0 here (The code will work even if count is 0) - */ - - { - /* First copy the data to Count */ - size_t len_in_buff = (size_t) (info->write_pos - info->append_read_pos); - size_t copy_len; - size_t transfer_len; - - DBUG_ASSERT(info->append_read_pos <= info->write_pos); - /* - TODO: figure out if the assert below is needed or correct. - */ - DBUG_ASSERT(pos_in_file == info->end_of_file); - copy_len=min(Count, len_in_buff); - memcpy(Buffer, info->append_read_pos, copy_len); - info->append_read_pos += copy_len; - Count -= copy_len; - if (Count) - info->error = save_count - Count; - - /* Fill read buffer with data from write buffer */ - memcpy(info->buffer, info->append_read_pos, - (size_t) (transfer_len=len_in_buff - copy_len)); - info->read_pos= info->buffer; - info->read_end= info->buffer+transfer_len; - info->append_read_pos=info->write_pos; - info->pos_in_file=pos_in_file+copy_len; - info->end_of_file+=len_in_buff; - } - unlock_append_buffer(info); - return Count ? 1 : 0; -} - - -#ifdef HAVE_AIOWAIT - -/* - Read from the IO_CACHE into a buffer and feed asynchronously - from disk when needed. - - SYNOPSIS - _my_b_async_read() - info IO_CACHE pointer - Buffer Buffer to retrieve count bytes from file - Count Number of bytes to read into Buffer - - RETURN VALUE - -1 An error has occurred; my_errno is set. - 0 Success - 1 An error has occurred; IO_CACHE to error state. -*/ - -int _my_b_async_read(register IO_CACHE *info, uchar *Buffer, size_t Count) -{ - size_t length,read_length,diff_length,left_length,use_length,org_Count; - size_t max_length; - my_off_t next_pos_in_file; - uchar *read_buffer; - - memcpy(Buffer,info->read_pos, - (left_length= (size_t) (info->read_end-info->read_pos))); - Buffer+=left_length; - org_Count=Count; - Count-=left_length; - - if (info->inited) - { /* wait for read block */ - info->inited=0; /* No more block to read */ - my_aiowait(&info->aio_result); /* Wait for outstanding req */ - if (info->aio_result.result.aio_errno) - { - if (info->myflags & MY_WME) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(info->file), - info->aio_result.result.aio_errno); - my_errno=info->aio_result.result.aio_errno; - info->error= -1; - return(1); - } - if (! (read_length= (size_t) info->aio_result.result.aio_return) || - read_length == (size_t) -1) - { - my_errno=0; /* For testing */ - info->error= (read_length == (size_t) -1 ? -1 : - (int) (read_length+left_length)); - return(1); - } - info->pos_in_file+= (size_t) (info->read_end - info->request_pos); - - if (info->request_pos != info->buffer) - info->request_pos=info->buffer; - else - info->request_pos=info->buffer+info->read_length; - info->read_pos=info->request_pos; - next_pos_in_file=info->aio_read_pos+read_length; - - /* Check if pos_in_file is changed - (_ni_read_cache may have skipped some bytes) */ - - if (info->aio_read_pos < info->pos_in_file) - { /* Fix if skipped bytes */ - if (info->aio_read_pos + read_length < info->pos_in_file) - { - read_length=0; /* Skip block */ - next_pos_in_file=info->pos_in_file; - } - else - { - my_off_t offset= (info->pos_in_file - info->aio_read_pos); - info->pos_in_file=info->aio_read_pos; /* Whe are here */ - info->read_pos=info->request_pos+offset; - read_length-=offset; /* Bytes left from read_pos */ - } - } -#ifndef DBUG_OFF - if (info->aio_read_pos > info->pos_in_file) - { - my_errno=EINVAL; - return(info->read_length= (size_t) -1); - } -#endif - /* Copy found bytes to buffer */ - length=min(Count,read_length); - memcpy(Buffer,info->read_pos,(size_t) length); - Buffer+=length; - Count-=length; - left_length+=length; - info->read_end=info->rc_pos+read_length; - info->read_pos+=length; - } - else - next_pos_in_file=(info->pos_in_file+ (size_t) - (info->read_end - info->request_pos)); - - /* If reading large blocks, or first read or read with skip */ - if (Count) - { - if (next_pos_in_file == info->end_of_file) - { - info->error=(int) (read_length+left_length); - return 1; - } - - if (mysql_file_seek(info->file, next_pos_in_file, MY_SEEK_SET, MYF(0)) - == MY_FILEPOS_ERROR) - { - info->error= -1; - return (1); - } - - read_length=IO_SIZE*2- (size_t) (next_pos_in_file & (IO_SIZE-1)); - if (Count < read_length) - { /* Small block, read to cache */ - if ((read_length=mysql_file_read(info->file,info->request_pos, - read_length, info->myflags)) == (size_t) -1) - return info->error= -1; - use_length=min(Count,read_length); - memcpy(Buffer,info->request_pos,(size_t) use_length); - info->read_pos=info->request_pos+Count; - info->read_end=info->request_pos+read_length; - info->pos_in_file=next_pos_in_file; /* Start of block in cache */ - next_pos_in_file+=read_length; - - if (Count != use_length) - { /* Didn't find hole block */ - if (info->myflags & (MY_WME | MY_FAE | MY_FNABP) && Count != org_Count) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(info->file),my_errno); - info->error=(int) (read_length+left_length); - return 1; - } - } - else - { /* Big block, don't cache it */ - if ((read_length= mysql_file_read(info->file, Buffer, Count,info->myflags)) - != Count) - { - info->error= read_length == (size_t) -1 ? -1 : read_length+left_length; - return 1; - } - info->read_pos=info->read_end=info->request_pos; - info->pos_in_file=(next_pos_in_file+=Count); - } - } - - /* Read next block with asyncronic io */ - diff_length=(next_pos_in_file & (IO_SIZE-1)); - max_length= info->read_length - diff_length; - if (max_length > info->end_of_file - next_pos_in_file) - max_length= (size_t) (info->end_of_file - next_pos_in_file); - - if (info->request_pos != info->buffer) - read_buffer=info->buffer; - else - read_buffer=info->buffer+info->read_length; - info->aio_read_pos=next_pos_in_file; - if (max_length) - { - info->aio_result.result.aio_errno=AIO_INPROGRESS; /* Marker for test */ - DBUG_PRINT("aioread",("filepos: %ld length: %lu", - (ulong) next_pos_in_file, (ulong) max_length)); - if (aioread(info->file,read_buffer, max_length, - (my_off_t) next_pos_in_file,MY_SEEK_SET, - &info->aio_result.result)) - { /* Skip async io */ - my_errno=errno; - DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped", - errno, info->aio_result.result.aio_errno)); - if (info->request_pos != info->buffer) - { - bmove(info->buffer,info->request_pos, - (size_t) (info->read_end - info->read_pos)); - info->request_pos=info->buffer; - info->read_pos-=info->read_length; - info->read_end-=info->read_length; - } - info->read_length=info->buffer_length; /* Use hole buffer */ - info->read_function=_my_b_read; /* Use normal IO_READ next */ - } - else - info->inited=info->aio_result.pending=1; - } - return 0; /* Block read, async in use */ -} /* _my_b_async_read */ -#endif - - -/* Read one byte when buffer is empty */ - -int _my_b_get(IO_CACHE *info) -{ - uchar buff; - IO_CACHE_CALLBACK pre_read,post_read; - if ((pre_read = info->pre_read)) - (*pre_read)(info); - if ((*(info)->read_function)(info,&buff,1)) - return my_b_EOF; - if ((post_read = info->post_read)) - (*post_read)(info); - return (int) (uchar) buff; -} - -/* - Write a byte buffer to IO_CACHE and flush to disk - if IO_CACHE is full. - - RETURN VALUE - 1 On error on write - 0 On success - -1 On error; my_errno contains error code. -*/ - -int _my_b_write(register IO_CACHE *info, const uchar *Buffer, size_t Count) -{ - size_t rest_length,length; - - if (info->pos_in_file+info->buffer_length > info->end_of_file) - { - my_errno=errno=EFBIG; - return info->error = -1; - } - - rest_length= (size_t) (info->write_end - info->write_pos); - memcpy(info->write_pos,Buffer,(size_t) rest_length); - Buffer+=rest_length; - Count-=rest_length; - info->write_pos+=rest_length; - - if (my_b_flush_io_cache(info,1)) - return 1; - if (Count >= IO_SIZE) - { /* Fill first intern buffer */ - length=Count & (size_t) ~(IO_SIZE-1); - if (info->seek_not_done) - { - /* - Whenever a function which operates on IO_CACHE flushes/writes - some part of the IO_CACHE to disk it will set the property - "seek_not_done" to indicate this to other functions operating - on the IO_CACHE. - */ - if (mysql_file_seek(info->file, info->pos_in_file, MY_SEEK_SET, MYF(0))) - { - info->error= -1; - return (1); - } - info->seek_not_done=0; - } - if (mysql_file_write(info->file, Buffer, length, info->myflags | MY_NABP)) - return info->error= -1; - - /* - In case of a shared I/O cache with a writer we normally do direct - write cache to read cache copy. Simulate this here by direct - caller buffer to read cache copy. Do it after the write so that - the cache readers actions on the flushed part can go in parallel - with the write of the extra stuff. copy_to_read_buffer() - synchronizes writer and readers so that after this call the - readers can act on the extra stuff while the writer can go ahead - and prepare the next output. copy_to_read_buffer() relies on - info->pos_in_file. - */ - if (info->share) - copy_to_read_buffer(info, Buffer, length); - - Count-=length; - Buffer+=length; - info->pos_in_file+=length; - } - memcpy(info->write_pos,Buffer,(size_t) Count); - info->write_pos+=Count; - return 0; -} - - -/* - Append a block to the write buffer. - This is done with the buffer locked to ensure that we don't read from - the write buffer before we are ready with it. -*/ - -int my_b_append(register IO_CACHE *info, const uchar *Buffer, size_t Count) -{ - size_t rest_length,length; - - /* - Assert that we cannot come here with a shared cache. If we do one - day, we might need to add a call to copy_to_read_buffer(). - */ - DBUG_ASSERT(!info->share); - - lock_append_buffer(info); - rest_length= (size_t) (info->write_end - info->write_pos); - if (Count <= rest_length) - goto end; - memcpy(info->write_pos, Buffer, rest_length); - Buffer+=rest_length; - Count-=rest_length; - info->write_pos+=rest_length; - if (my_b_flush_io_cache(info,0)) - { - unlock_append_buffer(info); - return 1; - } - if (Count >= IO_SIZE) - { /* Fill first intern buffer */ - length=Count & (size_t) ~(IO_SIZE-1); - if (mysql_file_write(info->file,Buffer, length, info->myflags | MY_NABP)) - { - unlock_append_buffer(info); - return info->error= -1; - } - Count-=length; - Buffer+=length; - info->end_of_file+=length; - } - -end: - memcpy(info->write_pos,Buffer,(size_t) Count); - info->write_pos+=Count; - unlock_append_buffer(info); - return 0; -} - - -int my_b_safe_write(IO_CACHE *info, const uchar *Buffer, size_t Count) -{ - /* - Sasha: We are not writing this with the ? operator to avoid hitting - a possible compiler bug. At least gcc 2.95 cannot deal with - several layers of ternary operators that evaluated comma(,) operator - expressions inside - I do have a test case if somebody wants it - */ - if (info->type == SEQ_READ_APPEND) - return my_b_append(info, Buffer, Count); - return my_b_write(info, Buffer, Count); -} - - -/* - Write a block to disk where part of the data may be inside the record - buffer. As all write calls to the data goes through the cache, - we will never get a seek over the end of the buffer -*/ - -int my_block_write(register IO_CACHE *info, const uchar *Buffer, size_t Count, - my_off_t pos) -{ - size_t length; - int error=0; - - /* - Assert that we cannot come here with a shared cache. If we do one - day, we might need to add a call to copy_to_read_buffer(). - */ - DBUG_ASSERT(!info->share); - - if (pos < info->pos_in_file) - { - /* Of no overlap, write everything without buffering */ - if (pos + Count <= info->pos_in_file) - return mysql_file_pwrite(info->file, Buffer, Count, pos, - info->myflags | MY_NABP); - /* Write the part of the block that is before buffer */ - length= (uint) (info->pos_in_file - pos); - if (mysql_file_pwrite(info->file, Buffer, length, pos, info->myflags | MY_NABP)) - info->error= error= -1; - Buffer+=length; - pos+= length; - Count-= length; -#ifndef HAVE_PREAD - info->seek_not_done=1; -#endif - } - - /* Check if we want to write inside the used part of the buffer.*/ - length= (size_t) (info->write_end - info->buffer); - if (pos < info->pos_in_file + length) - { - size_t offset= (size_t) (pos - info->pos_in_file); - length-=offset; - if (length > Count) - length=Count; - memcpy(info->buffer+offset, Buffer, length); - Buffer+=length; - Count-= length; - /* Fix length of buffer if the new data was larger */ - if (info->buffer+length > info->write_pos) - info->write_pos=info->buffer+length; - if (!Count) - return (error); - } - /* Write at the end of the current buffer; This is the normal case */ - if (_my_b_write(info, Buffer, Count)) - error= -1; - return error; -} - - - /* Flush write cache */ - -#define LOCK_APPEND_BUFFER if (need_append_buffer_lock) \ - lock_append_buffer(info); -#define UNLOCK_APPEND_BUFFER if (need_append_buffer_lock) \ - unlock_append_buffer(info); - -int my_b_flush_io_cache(IO_CACHE *info, - int need_append_buffer_lock __attribute__((unused))) -{ - size_t length; - my_off_t pos_in_file; - my_bool append_cache= (info->type == SEQ_READ_APPEND); - DBUG_ENTER("my_b_flush_io_cache"); - DBUG_PRINT("enter", ("cache: 0x%lx", (long) info)); - - if (!append_cache) - need_append_buffer_lock= 0; - - if (info->type == WRITE_CACHE || append_cache) - { - if (info->file == -1) - { - if (real_open_cached_file(info)) - DBUG_RETURN((info->error= -1)); - } - LOCK_APPEND_BUFFER; - - if ((length=(size_t) (info->write_pos - info->write_buffer))) - { - /* - In case of a shared I/O cache with a writer we do direct write - cache to read cache copy. Do it before the write here so that - the readers can work in parallel with the write. - copy_to_read_buffer() relies on info->pos_in_file. - */ - if (info->share) - copy_to_read_buffer(info, info->write_buffer, length); - - pos_in_file=info->pos_in_file; - /* - If we have append cache, we always open the file with - O_APPEND which moves the pos to EOF automatically on every write - */ - if (!append_cache && info->seek_not_done) - { /* File touched, do seek */ - if (mysql_file_seek(info->file, pos_in_file, MY_SEEK_SET, MYF(0)) == - MY_FILEPOS_ERROR) - { - UNLOCK_APPEND_BUFFER; - DBUG_RETURN((info->error= -1)); - } - if (!append_cache) - info->seek_not_done=0; - } - if (!append_cache) - info->pos_in_file+=length; - info->write_end= (info->write_buffer+info->buffer_length- - ((pos_in_file+length) & (IO_SIZE-1))); - - if (mysql_file_write(info->file,info->write_buffer,length, - info->myflags | MY_NABP)) - info->error= -1; - else - info->error= 0; - if (!append_cache) - { - set_if_bigger(info->end_of_file,(pos_in_file+length)); - } - else - { - info->end_of_file+=(info->write_pos-info->append_read_pos); - DBUG_ASSERT(info->end_of_file == mysql_file_tell(info->file, MYF(0))); - } - - info->append_read_pos=info->write_pos=info->write_buffer; - ++info->disk_writes; - UNLOCK_APPEND_BUFFER; - DBUG_RETURN(info->error); - } - } -#ifdef HAVE_AIOWAIT - else if (info->type != READ_NET) - { - my_aiowait(&info->aio_result); /* Wait for outstanding req */ - info->inited=0; - } -#endif - UNLOCK_APPEND_BUFFER; - DBUG_RETURN(0); -} - -/* - Free an IO_CACHE object - - SYNOPSOS - end_io_cache() - info IO_CACHE Handle to free - - NOTES - It's currently safe to call this if one has called init_io_cache() - on the 'info' object, even if init_io_cache() failed. - This function is also safe to call twice with the same handle. - - RETURN - 0 ok - # Error -*/ - -int end_io_cache(IO_CACHE *info) -{ - int error=0; - IO_CACHE_CALLBACK pre_close; - DBUG_ENTER("end_io_cache"); - DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info)); - - /* - Every thread must call remove_io_thread(). The last one destroys - the share elements. - */ - DBUG_ASSERT(!info->share || !info->share->total_threads); - - if ((pre_close=info->pre_close)) - { - (*pre_close)(info); - info->pre_close= 0; - } - if (info->alloced_buffer) - { - info->alloced_buffer=0; - if (info->file != -1) /* File doesn't exist */ - error= my_b_flush_io_cache(info,1); - my_free(info->buffer); - info->buffer=info->read_pos=(uchar*) 0; - } - if (info->type == SEQ_READ_APPEND) - { - /* Destroy allocated mutex */ - info->type= TYPE_NOT_SET; - mysql_mutex_destroy(&info->append_buffer_lock); - } - DBUG_RETURN(error); -} /* end_io_cache */ - - -/********************************************************************** - Testing of MF_IOCACHE -**********************************************************************/ - -#ifdef MAIN - -#include <my_dir.h> - -void die(const char* fmt, ...) -{ - va_list va_args; - va_start(va_args,fmt); - fprintf(stderr,"Error:"); - vfprintf(stderr, fmt,va_args); - fprintf(stderr,", errno=%d\n", errno); - exit(1); -} - -int open_file(const char* fname, IO_CACHE* info, int cache_size) -{ - int fd; - if ((fd=my_open(fname,O_CREAT | O_RDWR,MYF(MY_WME))) < 0) - die("Could not open %s", fname); - if (init_io_cache(info, fd, cache_size, SEQ_READ_APPEND, 0,0,MYF(MY_WME))) - die("failed in init_io_cache()"); - return fd; -} - -void close_file(IO_CACHE* info) -{ - end_io_cache(info); - my_close(info->file, MYF(MY_WME)); -} - -int main(int argc, char** argv) -{ - IO_CACHE sra_cache; /* SEQ_READ_APPEND */ - MY_STAT status; - const char* fname="/tmp/iocache.test"; - int cache_size=16384; - char llstr_buf[22]; - int max_block,total_bytes=0; - int i,num_loops=100,error=0; - char *p; - char* block, *block_end; - MY_INIT(argv[0]); - max_block = cache_size*3; - if (!(block=(char*)my_malloc(max_block,MYF(MY_WME)))) - die("Not enough memory to allocate test block"); - block_end = block + max_block; - for (p = block,i=0; p < block_end;i++) - { - *p++ = (char)i; - } - if (my_stat(fname,&status, MYF(0)) && - my_delete(fname,MYF(MY_WME))) - { - die("Delete of %s failed, aborting", fname); - } - open_file(fname,&sra_cache, cache_size); - for (i = 0; i < num_loops; i++) - { - char buf[4]; - int block_size = abs(rand() % max_block); - int4store(buf, block_size); - if (my_b_append(&sra_cache,buf,4) || - my_b_append(&sra_cache, block, block_size)) - die("write failed"); - total_bytes += 4+block_size; - } - close_file(&sra_cache); - my_free(block); - if (!my_stat(fname,&status,MYF(MY_WME))) - die("%s failed to stat, but I had just closed it,\ - wonder how that happened"); - printf("Final size of %s is %s, wrote %d bytes\n",fname, - llstr(status.st_size,llstr_buf), - total_bytes); - my_delete(fname, MYF(MY_WME)); - /* check correctness of tests */ - if (total_bytes != status.st_size) - { - fprintf(stderr,"Not the same number of bytes acutally in file as bytes \ -supposedly written\n"); - error=1; - } - exit(error); - return 0; -} -#endif diff --git a/dep/mysqllite/mysys/mf_iocache2.c b/dep/mysqllite/mysys/mf_iocache2.c deleted file mode 100644 index 8962a037da0..00000000000 --- a/dep/mysqllite/mysys/mf_iocache2.c +++ /dev/null @@ -1,472 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* - More functions to be used with IO_CACHE files -*/ - -#include "mysys_priv.h" -#include <m_string.h> -#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) -{ - size_t 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); - do - { - if (my_fwrite(file, cache->read_pos, bytes_in_cache, - MYF(MY_WME | MY_NABP)) == (size_t) -1) - DBUG_RETURN(1); - cache->read_pos= cache->read_end; - } while ((bytes_in_cache= my_b_fill(cache))); - DBUG_RETURN(0); -} - - -my_off_t my_b_append_tell(IO_CACHE* info) -{ - /* - Sometimes we want to make sure that the variable is not put into - a register in debugging mode so we can see its value in the core - */ -#ifndef DBUG_OFF -# define dbug_volatile volatile -#else -# define dbug_volatile -#endif - - /* - Prevent optimizer from putting res in a register when debugging - we need this to be able to see the value of res when the assert fails - */ - dbug_volatile my_off_t res; - - /* - We need to lock the append buffer mutex to keep flush_io_cache() - from messing with the variables that we need in order to provide the - answer to the question. - */ - mysql_mutex_lock(&info->append_buffer_lock); - -#ifndef DBUG_OFF - /* - Make sure EOF is where we think it is. Note that we cannot just use - my_tell() because we have a reader thread that could have left the - file offset in a non-EOF location - */ - { - volatile my_off_t save_pos; - save_pos = my_tell(info->file,MYF(0)); - my_seek(info->file,(my_off_t)0,MY_SEEK_END,MYF(0)); - /* - Save the value of my_tell in res so we can see it when studying coredump - */ - DBUG_ASSERT(info->end_of_file - (info->append_read_pos-info->write_buffer) - == (res=my_tell(info->file,MYF(0)))); - my_seek(info->file,save_pos,MY_SEEK_SET,MYF(0)); - } -#endif - res = info->end_of_file + (info->write_pos-info->append_read_pos); - mysql_mutex_unlock(&info->append_buffer_lock); - return res; -} - -my_off_t my_b_safe_tell(IO_CACHE *info) -{ - if (unlikely(info->type == SEQ_READ_APPEND)) - return my_b_append_tell(info); - return my_b_tell(info); -} - -/* - Make next read happen at the given position - For write cache, make next write happen at the given position -*/ - -void my_b_seek(IO_CACHE *info,my_off_t pos) -{ - my_off_t offset; - DBUG_ENTER("my_b_seek"); - DBUG_PRINT("enter",("pos: %lu", (ulong) pos)); - - /* - TODO: - Verify that it is OK to do seek in the non-append - area in SEQ_READ_APPEND cache - a) see if this always works - b) see if there is a better way to make it work - */ - if (info->type == SEQ_READ_APPEND) - (void) flush_io_cache(info); - - offset=(pos - info->pos_in_file); - - if (info->type == READ_CACHE || info->type == SEQ_READ_APPEND) - { - /* TODO: explain why this works if pos < info->pos_in_file */ - if ((ulonglong) offset < (ulonglong) (info->read_end - info->buffer)) - { - /* The read is in the current buffer; Reuse it */ - info->read_pos = info->buffer + offset; - DBUG_VOID_RETURN; - } - else - { - /* Force a new read on next my_b_read */ - info->read_pos=info->read_end=info->buffer; - } - } - else if (info->type == WRITE_CACHE) - { - /* If write is in current buffer, reuse it */ - if ((ulonglong) offset < - (ulonglong) (info->write_end - info->write_buffer)) - { - info->write_pos = info->write_buffer + offset; - DBUG_VOID_RETURN; - } - (void) flush_io_cache(info); - /* Correct buffer end so that we write in increments of IO_SIZE */ - info->write_end=(info->write_buffer+info->buffer_length- - (pos & (IO_SIZE-1))); - } - info->pos_in_file=pos; - info->seek_not_done=1; - DBUG_VOID_RETURN; -} - - -/* - Fill buffer of the cache. - - NOTES - This assumes that you have already used all characters in the CACHE, - independent of the read_pos value! - - RETURN - 0 On error or EOF (info->error = -1 on error) - # Number of characters -*/ - - -size_t my_b_fill(IO_CACHE *info) -{ - my_off_t pos_in_file=(info->pos_in_file+ - (size_t) (info->read_end - info->buffer)); - size_t diff_length, length, max_length; - - if (info->seek_not_done) - { /* File touched, do seek */ - if (my_seek(info->file,pos_in_file,MY_SEEK_SET,MYF(0)) == - MY_FILEPOS_ERROR) - { - info->error= 0; - return 0; - } - info->seek_not_done=0; - } - diff_length=(size_t) (pos_in_file & (IO_SIZE-1)); - max_length=(info->read_length-diff_length); - if (max_length >= (info->end_of_file - pos_in_file)) - max_length= (size_t) (info->end_of_file - pos_in_file); - - if (!max_length) - { - info->error= 0; - return 0; /* EOF */ - } - if ((length= my_read(info->file,info->buffer,max_length, - info->myflags)) == (size_t) -1) - { - info->error= -1; - return 0; - } - info->read_pos=info->buffer; - info->read_end=info->buffer+length; - info->pos_in_file=pos_in_file; - return length; -} - - -/* - Read a string ended by '\n' into a buffer of 'max_length' size. - Returns number of characters read, 0 on error. - last byte is set to '\0' - If buffer is full then to[max_length-1] will be set to \0. -*/ - -size_t my_b_gets(IO_CACHE *info, char *to, size_t max_length) -{ - char *start = to; - size_t length; - max_length--; /* Save place for end \0 */ - - /* Calculate number of characters in buffer */ - if (!(length= my_b_bytes_in_cache(info)) && - !(length= my_b_fill(info))) - return 0; - - for (;;) - { - uchar *pos, *end; - if (length > max_length) - length=max_length; - for (pos=info->read_pos,end=pos+length ; pos < end ;) - { - if ((*to++ = *pos++) == '\n') - { - info->read_pos=pos; - *to='\0'; - return (size_t) (to-start); - } - } - if (!(max_length-=length)) - { - /* Found enough charcters; Return found string */ - info->read_pos=pos; - *to='\0'; - return (size_t) (to-start); - } - if (!(length=my_b_fill(info))) - return 0; - } -} - - -my_off_t my_b_filelength(IO_CACHE *info) -{ - if (info->type == WRITE_CACHE) - return my_b_tell(info); - - info->seek_not_done= 1; - return my_seek(info->file, 0L, MY_SEEK_END, MYF(0)); -} - - -/* - Simple printf version. Supports '%s', '%d', '%u', "%ld" and "%lu" - Used for logging in MySQL - returns number of written character, or (size_t) -1 on error -*/ - -size_t my_b_printf(IO_CACHE *info, const char* fmt, ...) -{ - size_t result; - va_list args; - va_start(args,fmt); - result=my_b_vprintf(info, fmt, args); - va_end(args); - return result; -} - - -size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list args) -{ - size_t out_length= 0; - uint minimum_width; /* as yet unimplemented */ - uint minimum_width_sign; - uint precision; /* as yet unimplemented for anything but %b */ - my_bool is_zero_padded; - - /* - Store the location of the beginning of a format directive, for the - case where we learn we shouldn't have been parsing a format string - at all, and we don't want to lose the flag/precision/width/size - information. - */ - const char* backtrack; - - for (; *fmt != '\0'; fmt++) - { - /* Copy everything until '%' or end of string */ - const char *start=fmt; - size_t length; - - for (; (*fmt != '\0') && (*fmt != '%'); fmt++) ; - - length= (size_t) (fmt - start); - out_length+=length; - if (my_b_write(info, (const uchar*) start, length)) - goto err; - - if (*fmt == '\0') /* End of format */ - return out_length; - - /* - By this point, *fmt must be a percent; Keep track of this location and - skip over the percent character. - */ - DBUG_ASSERT(*fmt == '%'); - backtrack= fmt; - fmt++; - - is_zero_padded= FALSE; - minimum_width_sign= 1; - minimum_width= 0; - precision= 0; - /* Skip if max size is used (to be compatible with printf) */ - -process_flags: - switch (*fmt) - { - case '-': - minimum_width_sign= -1; fmt++; goto process_flags; - case '0': - is_zero_padded= TRUE; fmt++; goto process_flags; - case '#': - /** @todo Implement "#" conversion flag. */ fmt++; goto process_flags; - case ' ': - /** @todo Implement " " conversion flag. */ fmt++; goto process_flags; - case '+': - /** @todo Implement "+" conversion flag. */ fmt++; goto process_flags; - } - - if (*fmt == '*') - { - precision= (int) va_arg(args, int); - fmt++; - } - else - { - while (my_isdigit(&my_charset_latin1, *fmt)) { - minimum_width=(minimum_width * 10) + (*fmt - '0'); - fmt++; - } - } - minimum_width*= minimum_width_sign; - - if (*fmt == '.') - { - fmt++; - if (*fmt == '*') { - precision= (int) va_arg(args, int); - fmt++; - } - else - { - while (my_isdigit(&my_charset_latin1, *fmt)) { - precision=(precision * 10) + (*fmt - '0'); - fmt++; - } - } - } - - if (*fmt == 's') /* String parameter */ - { - reg2 char *par = va_arg(args, char *); - size_t length2 = strlen(par); - /* TODO: implement precision */ - out_length+= length2; - if (my_b_write(info, (uchar*) par, length2)) - goto err; - } - else if (*fmt == 'b') /* Sized buffer parameter, only precision makes sense */ - { - char *par = va_arg(args, char *); - out_length+= precision; - if (my_b_write(info, (uchar*) par, precision)) - goto err; - } - else if (*fmt == 'd' || *fmt == 'u') /* Integer parameter */ - { - register int iarg; - size_t length2; - char buff[17]; - - iarg = va_arg(args, int); - if (*fmt == 'd') - length2= (size_t) (int10_to_str((long) iarg,buff, -10) - buff); - else - length2= (uint) (int10_to_str((long) (uint) iarg,buff,10)- buff); - - /* minimum width padding */ - if (minimum_width > length2) - { - char *buffz; - - buffz= my_alloca(minimum_width - length2); - if (is_zero_padded) - memset(buffz, '0', minimum_width - length2); - else - memset(buffz, ' ', minimum_width - length2); - my_b_write(info, buffz, minimum_width - length2); - my_afree(buffz); - } - - out_length+= length2; - if (my_b_write(info, (uchar*) buff, length2)) - goto err; - } - else if ((*fmt == 'l' && fmt[1] == 'd') || fmt[1] == 'u') - /* long parameter */ - { - register long iarg; - size_t length2; - char buff[17]; - - iarg = va_arg(args, long); - if (*++fmt == 'd') - length2= (size_t) (int10_to_str(iarg,buff, -10) - buff); - else - length2= (size_t) (int10_to_str(iarg,buff,10)- buff); - out_length+= length2; - if (my_b_write(info, (uchar*) buff, length2)) - goto err; - } - else - { - /* %% or unknown code */ - if (my_b_write(info, (uchar*) backtrack, (size_t) (fmt-backtrack))) - goto err; - out_length+= fmt-backtrack; - } - } - return out_length; - -err: - return (size_t) -1; -} diff --git a/dep/mysqllite/mysys/mf_keycache.c b/dep/mysqllite/mysys/mf_keycache.c deleted file mode 100644 index 42cdea65f34..00000000000 --- a/dep/mysqllite/mysys/mf_keycache.c +++ /dev/null @@ -1,4523 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/** - @file - These functions handle keyblock cacheing for ISAM and MyISAM tables. - - One cache can handle many files. - It must contain buffers of the same blocksize. - init_key_cache() should be used to init cache handler. - - The free list (free_block_list) is a stack like structure. - When a block is freed by free_block(), it is pushed onto the stack. - When a new block is required it is first tried to pop one from the stack. - If the stack is empty, it is tried to get a never-used block from the pool. - If this is empty too, then a block is taken from the LRU ring, flushing it - to disk, if neccessary. This is handled in find_key_block(). - With the new free list, the blocks can have three temperatures: - hot, warm and cold (which is free). This is remembered in the block header - by the enum BLOCK_TEMPERATURE temperature variable. Remembering the - temperature is neccessary to correctly count the number of warm blocks, - which is required to decide when blocks are allowed to become hot. Whenever - a block is inserted to another (sub-)chain, we take the old and new - temperature into account to decide if we got one more or less warm block. - blocks_unused is the sum of never used blocks in the pool and of currently - free blocks. blocks_used is the number of blocks fetched from the pool and - as such gives the maximum number of in-use blocks at any time. -*/ - -/* - Key Cache Locking - ================= - - All key cache locking is done with a single mutex per key cache: - keycache->cache_lock. This mutex is locked almost all the time - when executing code in this file (mf_keycache.c). - However it is released for I/O and some copy operations. - - The cache_lock is also released when waiting for some event. Waiting - and signalling is done via condition variables. In most cases the - thread waits on its thread->suspend condition variable. Every thread - has a my_thread_var structure, which contains this variable and a - '*next' and '**prev' pointer. These pointers are used to insert the - thread into a wait queue. - - A thread can wait for one block and thus be in one wait queue at a - time only. - - Before starting to wait on its condition variable with - mysql_cond_wait(), the thread enters itself to a specific wait queue - with link_into_queue() (double linked with '*next' + '**prev') or - wait_on_queue() (single linked with '*next'). - - Another thread, when releasing a resource, looks up the waiting thread - in the related wait queue. It sends a signal with - mysql_cond_signal() to the waiting thread. - - NOTE: Depending on the particular wait situation, either the sending - thread removes the waiting thread from the wait queue with - unlink_from_queue() or release_whole_queue() respectively, or the waiting - thread removes itself. - - There is one exception from this locking scheme when one thread wants - to reuse a block for some other address. This works by first marking - the block reserved (status= BLOCK_IN_SWITCH) and then waiting for all - threads that are reading the block to finish. Each block has a - reference to a condition variable (condvar). It holds a reference to - the thread->suspend condition variable for the waiting thread (if such - a thread exists). When that thread is signaled, the reference is - cleared. The number of readers of a block is registered in - block->hash_link->requests. See wait_for_readers() / remove_reader() - for details. This is similar to the above, but it clearly means that - only one thread can wait for a particular block. There is no queue in - this case. Strangely enough block->convar is used for waiting for the - assigned hash_link only. More precisely it is used to wait for all - requests to be unregistered from the assigned hash_link. - - The resize_queue serves two purposes: - 1. Threads that want to do a resize wait there if in_resize is set. - This is not used in the server. The server refuses a second resize - request if one is already active. keycache->in_init is used for the - synchronization. See set_var.cc. - 2. Threads that want to access blocks during resize wait here during - the re-initialization phase. - When the resize is done, all threads on the queue are signalled. - Hypothetical resizers can compete for resizing, and read/write - requests will restart to request blocks from the freshly resized - cache. If the cache has been resized too small, it is disabled and - 'can_be_used' is false. In this case read/write requests bypass the - cache. Since they increment and decrement 'cnt_for_resize_op', the - next resizer can wait on the queue 'waiting_for_resize_cnt' until all - I/O finished. -*/ - -#include "mysys_priv.h" -#include "mysys_err.h" -#include <keycache.h> -#include "my_static.h" -#include <m_string.h> -#include <my_bit.h> -#include <errno.h> -#include <stdarg.h> -#include "probes_mysql.h" - -/* - Some compilation flags have been added specifically for this module - to control the following: - - not to let a thread to yield the control when reading directly - from key cache, which might improve performance in many cases; - to enable this add: - #define SERIALIZED_READ_FROM_CACHE - - to set an upper bound for number of threads simultaneously - using the key cache; this setting helps to determine an optimal - size for hash table and improve performance when the number of - blocks in the key cache much less than the number of threads - accessing it; - to set this number equal to <N> add - #define MAX_THREADS <N> - - to substitute calls of mysql_cond_wait for calls of - mysql_cond_timedwait (wait with timeout set up); - this setting should be used only when you want to trap a deadlock - situation, which theoretically should not happen; - to set timeout equal to <T> seconds add - #define KEYCACHE_TIMEOUT <T> - - to enable the module traps and to send debug information from - key cache module to a special debug log add: - #define KEYCACHE_DEBUG - the name of this debug log file <LOG NAME> can be set through: - #define KEYCACHE_DEBUG_LOG <LOG NAME> - if the name is not defined, it's set by default; - if the KEYCACHE_DEBUG flag is not set up and we are in a debug - mode, i.e. when ! defined(DBUG_OFF), the debug information from the - module is sent to the regular debug log. - - Example of the settings: - #define SERIALIZED_READ_FROM_CACHE - #define MAX_THREADS 100 - #define KEYCACHE_TIMEOUT 1 - #define KEYCACHE_DEBUG - #define KEYCACHE_DEBUG_LOG "my_key_cache_debug.log" -*/ - -#define STRUCT_PTR(TYPE, MEMBER, a) \ - (TYPE *) ((char *) (a) - offsetof(TYPE, MEMBER)) - -/* types of condition variables */ -#define COND_FOR_REQUESTED 0 -#define COND_FOR_SAVED 1 -#define COND_FOR_READERS 2 - -typedef mysql_cond_t KEYCACHE_CONDVAR; - -/* descriptor of the page in the key cache block buffer */ -struct st_keycache_page -{ - int file; /* file to which the page belongs to */ - my_off_t filepos; /* position of the page in the file */ -}; - -/* element in the chain of a hash table bucket */ -struct st_hash_link -{ - struct st_hash_link *next, **prev; /* to connect links in the same bucket */ - struct st_block_link *block; /* reference to the block for the page: */ - File file; /* from such a file */ - my_off_t diskpos; /* with such an offset */ - uint requests; /* number of requests for the page */ -}; - -/* simple states of a block */ -#define BLOCK_ERROR 1 /* an error occured when performing file i/o */ -#define BLOCK_READ 2 /* file block is in the block buffer */ -#define BLOCK_IN_SWITCH 4 /* block is preparing to read new page */ -#define BLOCK_REASSIGNED 8 /* blk does not accept requests for old page */ -#define BLOCK_IN_FLUSH 16 /* block is selected for flush */ -#define BLOCK_CHANGED 32 /* block buffer contains a dirty page */ -#define BLOCK_IN_USE 64 /* block is not free */ -#define BLOCK_IN_EVICTION 128 /* block is selected for eviction */ -#define BLOCK_IN_FLUSHWRITE 256 /* block is in write to file */ -#define BLOCK_FOR_UPDATE 512 /* block is selected for buffer modification */ - -/* page status, returned by find_key_block */ -#define PAGE_READ 0 -#define PAGE_TO_BE_READ 1 -#define PAGE_WAIT_TO_BE_READ 2 - -/* block temperature determines in which (sub-)chain the block currently is */ -enum BLOCK_TEMPERATURE { BLOCK_COLD /*free*/ , BLOCK_WARM , BLOCK_HOT }; - -/* key cache block */ -struct st_block_link -{ - struct st_block_link - *next_used, **prev_used; /* to connect links in the LRU chain (ring) */ - struct st_block_link - *next_changed, **prev_changed; /* for lists of file dirty/clean blocks */ - struct st_hash_link *hash_link; /* backward ptr to referring hash_link */ - KEYCACHE_WQUEUE wqueue[2]; /* queues on waiting requests for new/old pages */ - uint requests; /* number of requests for the block */ - uchar *buffer; /* buffer for the block page */ - uint offset; /* beginning of modified data in the buffer */ - uint length; /* end of data in the buffer */ - uint status; /* state of the block */ - enum BLOCK_TEMPERATURE temperature; /* block temperature: cold, warm, hot */ - uint hits_left; /* number of hits left until promotion */ - ulonglong last_hit_time; /* timestamp of the last hit */ - KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event */ -}; - -KEY_CACHE dflt_key_cache_var; -KEY_CACHE *dflt_key_cache= &dflt_key_cache_var; - -#define FLUSH_CACHE 2000 /* sort this many blocks at once */ - -static int flush_all_key_blocks(KEY_CACHE *keycache); - -static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, - mysql_mutex_t *mutex); -static void release_whole_queue(KEYCACHE_WQUEUE *wqueue); - -static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block); -#if !defined(DBUG_OFF) -static void test_key_cache(KEY_CACHE *keycache, - const char *where, my_bool lock); -#endif - -#define KEYCACHE_HASH(f, pos) \ -(((ulong) ((pos) / keycache->key_cache_block_size) + \ - (ulong) (f)) & (keycache->hash_entries-1)) -#define FILE_HASH(f) ((uint) (f) & (CHANGED_BLOCKS_HASH-1)) - -#define DEFAULT_KEYCACHE_DEBUG_LOG "keycache_debug.log" - -#if defined(KEYCACHE_DEBUG) && ! defined(KEYCACHE_DEBUG_LOG) -#define KEYCACHE_DEBUG_LOG DEFAULT_KEYCACHE_DEBUG_LOG -#endif - -#if defined(KEYCACHE_DEBUG_LOG) -static FILE *keycache_debug_log=NULL; -static void keycache_debug_print(const char *fmt,...); -#define KEYCACHE_DEBUG_OPEN \ - if (!keycache_debug_log) \ - { \ - keycache_debug_log= fopen(KEYCACHE_DEBUG_LOG, "w"); \ - (void) setvbuf(keycache_debug_log, NULL, _IOLBF, BUFSIZ); \ - } - -#define KEYCACHE_DEBUG_CLOSE \ - if (keycache_debug_log) \ - { \ - fclose(keycache_debug_log); \ - keycache_debug_log= 0; \ - } -#else -#define KEYCACHE_DEBUG_OPEN -#define KEYCACHE_DEBUG_CLOSE -#endif /* defined(KEYCACHE_DEBUG_LOG) */ - -#if defined(KEYCACHE_DEBUG_LOG) && defined(KEYCACHE_DEBUG) -#define KEYCACHE_DBUG_PRINT(l, m) \ - { if (keycache_debug_log) fprintf(keycache_debug_log, "%s: ", l); \ - keycache_debug_print m; } - -#define KEYCACHE_DBUG_ASSERT(a) \ - { if (! (a) && keycache_debug_log) fclose(keycache_debug_log); \ - assert(a); } -#else -#define KEYCACHE_DBUG_PRINT(l, m) DBUG_PRINT(l, m) -#define KEYCACHE_DBUG_ASSERT(a) DBUG_ASSERT(a) -#endif /* defined(KEYCACHE_DEBUG_LOG) && defined(KEYCACHE_DEBUG) */ - -#if defined(KEYCACHE_DEBUG) || !defined(DBUG_OFF) - -static long keycache_thread_id; -#define KEYCACHE_THREAD_TRACE(l) \ - KEYCACHE_DBUG_PRINT(l,("|thread %ld",keycache_thread_id)) - -#define KEYCACHE_THREAD_TRACE_BEGIN(l) \ - { struct st_my_thread_var *thread_var= my_thread_var; \ - keycache_thread_id= thread_var->id; \ - KEYCACHE_DBUG_PRINT(l,("[thread %ld",keycache_thread_id)) } - -#define KEYCACHE_THREAD_TRACE_END(l) \ - KEYCACHE_DBUG_PRINT(l,("]thread %ld",keycache_thread_id)) -#else -#define KEYCACHE_THREAD_TRACE_BEGIN(l) -#define KEYCACHE_THREAD_TRACE_END(l) -#define KEYCACHE_THREAD_TRACE(l) -#endif /* defined(KEYCACHE_DEBUG) || !defined(DBUG_OFF) */ - -#define BLOCK_NUMBER(b) \ - ((uint) (((char*)(b)-(char *) keycache->block_root)/sizeof(BLOCK_LINK))) -#define HASH_LINK_NUMBER(h) \ - ((uint) (((char*)(h)-(char *) keycache->hash_link_root)/sizeof(HASH_LINK))) - -#if (defined(KEYCACHE_TIMEOUT) && !defined(__WIN__)) || defined(KEYCACHE_DEBUG) -static int keycache_pthread_cond_wait(mysql_cond_t *cond, - mysql_mutex_t *mutex); -#else -#define keycache_pthread_cond_wait(C, M) mysql_cond_wait(C, M) -#endif - -#if defined(KEYCACHE_DEBUG) -static int keycache_pthread_mutex_lock(mysql_mutex_t *mutex); -static void keycache_pthread_mutex_unlock(mysql_mutex_t *mutex); -static int keycache_pthread_cond_signal(mysql_cond_t *cond); -#else -#define keycache_pthread_mutex_lock(M) mysql_mutex_lock(M) -#define keycache_pthread_mutex_unlock(M) mysql_mutex_unlock(M) -#define keycache_pthread_cond_signal(C) mysql_cond_signal(C) -#endif /* defined(KEYCACHE_DEBUG) */ - -#if !defined(DBUG_OFF) -#if defined(inline) -#undef inline -#endif -#define inline /* disabled inline for easier debugging */ -static int fail_block(BLOCK_LINK *block); -static int fail_hlink(HASH_LINK *hlink); -static int cache_empty(KEY_CACHE *keycache); -#endif - -static inline uint next_power(uint value) -{ - return (uint) my_round_up_to_next_power((uint32) value) << 1; -} - - -/* - Initialize a key cache - - SYNOPSIS - init_key_cache() - keycache pointer to a key cache data structure - key_cache_block_size size of blocks to keep cached data - use_mem total memory to use for the key cache - division_limit division limit (may be zero) - age_threshold age threshold (may be zero) - - RETURN VALUE - number of blocks in the key cache, if successful, - 0 - otherwise. - - NOTES. - if keycache->key_cache_inited != 0 we assume that the key cache - is already initialized. This is for now used by myisamchk, but shouldn't - be something that a program should rely on! - - It's assumed that no two threads call this function simultaneously - referring to the same key cache handle. - -*/ - -int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, - size_t use_mem, uint division_limit, - uint age_threshold) -{ - ulong blocks, hash_links; - size_t length; - int error; - DBUG_ENTER("init_key_cache"); - DBUG_ASSERT(key_cache_block_size >= 512); - - KEYCACHE_DEBUG_OPEN; - if (keycache->key_cache_inited && keycache->disk_blocks > 0) - { - DBUG_PRINT("warning",("key cache already in use")); - DBUG_RETURN(0); - } - - keycache->global_cache_w_requests= keycache->global_cache_r_requests= 0; - keycache->global_cache_read= keycache->global_cache_write= 0; - keycache->disk_blocks= -1; - if (! keycache->key_cache_inited) - { - keycache->key_cache_inited= 1; - /* - Initialize these variables once only. - Their value must survive re-initialization during resizing. - */ - keycache->in_resize= 0; - keycache->resize_in_flush= 0; - keycache->cnt_for_resize_op= 0; - keycache->waiting_for_resize_cnt.last_thread= NULL; - keycache->in_init= 0; - mysql_mutex_init(key_KEY_CACHE_cache_lock, - &keycache->cache_lock, MY_MUTEX_INIT_FAST); - keycache->resize_queue.last_thread= NULL; - } - - keycache->key_cache_mem_size= use_mem; - keycache->key_cache_block_size= key_cache_block_size; - DBUG_PRINT("info", ("key_cache_block_size: %u", - key_cache_block_size)); - - blocks= (ulong) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) + - sizeof(HASH_LINK*) * 5/4 + key_cache_block_size)); - /* It doesn't make sense to have too few blocks (less than 8) */ - if (blocks >= 8) - { - for ( ; ; ) - { - /* Set my_hash_entries to the next bigger 2 power */ - if ((keycache->hash_entries= next_power(blocks)) < blocks * 5/4) - keycache->hash_entries<<= 1; - hash_links= 2 * blocks; -#if defined(MAX_THREADS) - if (hash_links < MAX_THREADS + blocks - 1) - hash_links= MAX_THREADS + blocks - 1; -#endif - while ((length= (ALIGN_SIZE(blocks * sizeof(BLOCK_LINK)) + - ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) + - ALIGN_SIZE(sizeof(HASH_LINK*) * - keycache->hash_entries))) + - ((size_t) blocks * keycache->key_cache_block_size) > use_mem) - blocks--; - /* Allocate memory for cache page buffers */ - if ((keycache->block_mem= - my_large_malloc((size_t) blocks * keycache->key_cache_block_size, - MYF(0)))) - { - /* - Allocate memory for blocks, hash_links and hash entries; - For each block 2 hash links are allocated - */ - if ((keycache->block_root= (BLOCK_LINK*) my_malloc(length, - MYF(0)))) - break; - my_large_free(keycache->block_mem); - keycache->block_mem= 0; - } - if (blocks < 8) - { - my_errno= ENOMEM; - my_error(EE_OUTOFMEMORY, MYF(0), blocks * keycache->key_cache_block_size); - goto err; - } - blocks= blocks / 4*3; - } - keycache->blocks_unused= blocks; - keycache->disk_blocks= (int) blocks; - keycache->hash_links= hash_links; - keycache->hash_root= (HASH_LINK**) ((char*) keycache->block_root + - ALIGN_SIZE(blocks*sizeof(BLOCK_LINK))); - keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root + - ALIGN_SIZE((sizeof(HASH_LINK*) * - keycache->hash_entries))); - bzero((uchar*) keycache->block_root, - keycache->disk_blocks * sizeof(BLOCK_LINK)); - bzero((uchar*) keycache->hash_root, - keycache->hash_entries * sizeof(HASH_LINK*)); - bzero((uchar*) keycache->hash_link_root, - keycache->hash_links * sizeof(HASH_LINK)); - keycache->hash_links_used= 0; - keycache->free_hash_list= NULL; - keycache->blocks_used= keycache->blocks_changed= 0; - - keycache->global_blocks_changed= 0; - keycache->blocks_available=0; /* For debugging */ - - /* The LRU chain is empty after initialization */ - keycache->used_last= NULL; - keycache->used_ins= NULL; - keycache->free_block_list= NULL; - keycache->keycache_time= 0; - keycache->warm_blocks= 0; - keycache->min_warm_blocks= (division_limit ? - blocks * division_limit / 100 + 1 : - blocks); - keycache->age_threshold= (age_threshold ? - blocks * age_threshold / 100 : - blocks); - - keycache->can_be_used= 1; - - keycache->waiting_for_hash_link.last_thread= NULL; - keycache->waiting_for_block.last_thread= NULL; - DBUG_PRINT("exit", - ("disk_blocks: %d block_root: 0x%lx hash_entries: %d\ - hash_root: 0x%lx hash_links: %d hash_link_root: 0x%lx", - keycache->disk_blocks, (long) keycache->block_root, - keycache->hash_entries, (long) keycache->hash_root, - keycache->hash_links, (long) keycache->hash_link_root)); - bzero((uchar*) keycache->changed_blocks, - sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH); - bzero((uchar*) keycache->file_blocks, - sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH); - } - else - { - /* key_buffer_size is specified too small. Disable the cache. */ - keycache->can_be_used= 0; - } - - keycache->blocks= keycache->disk_blocks > 0 ? keycache->disk_blocks : 0; - DBUG_RETURN((int) keycache->disk_blocks); - -err: - error= my_errno; - keycache->disk_blocks= 0; - keycache->blocks= 0; - if (keycache->block_mem) - { - my_large_free((uchar*) keycache->block_mem); - keycache->block_mem= NULL; - } - if (keycache->block_root) - { - my_free(keycache->block_root); - keycache->block_root= NULL; - } - my_errno= error; - keycache->can_be_used= 0; - DBUG_RETURN(0); -} - - -/* - Resize a key cache - - SYNOPSIS - resize_key_cache() - keycache pointer to a key cache data structure - key_cache_block_size size of blocks to keep cached data - use_mem total memory to use for the new key cache - division_limit new division limit (if not zero) - age_threshold new age threshold (if not zero) - - RETURN VALUE - number of blocks in the key cache, if successful, - 0 - otherwise. - - NOTES. - The function first compares the memory size and the block size parameters - with the key cache values. - - If they differ the function free the the memory allocated for the - old key cache blocks by calling the end_key_cache function and - then rebuilds the key cache with new blocks by calling - init_key_cache. - - The function starts the operation only when all other threads - performing operations with the key cache let her to proceed - (when cnt_for_resize=0). -*/ - -int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size, - size_t use_mem, uint division_limit, - uint age_threshold) -{ - int blocks; - DBUG_ENTER("resize_key_cache"); - - if (!keycache->key_cache_inited) - DBUG_RETURN(keycache->disk_blocks); - - if(key_cache_block_size == keycache->key_cache_block_size && - use_mem == keycache->key_cache_mem_size) - { - change_key_cache_param(keycache, division_limit, age_threshold); - DBUG_RETURN(keycache->disk_blocks); - } - - keycache_pthread_mutex_lock(&keycache->cache_lock); - - /* - We may need to wait for another thread which is doing a resize - already. This cannot happen in the MySQL server though. It allows - one resizer only. In set_var.cc keycache->in_init is used to block - multiple attempts. - */ - while (keycache->in_resize) - { - /* purecov: begin inspected */ - wait_on_queue(&keycache->resize_queue, &keycache->cache_lock); - /* purecov: end */ - } - - /* - Mark the operation in progress. This blocks other threads from doing - a resize in parallel. It prohibits new blocks to enter the cache. - Read/write requests can bypass the cache during the flush phase. - */ - keycache->in_resize= 1; - - /* Need to flush only if keycache is enabled. */ - if (keycache->can_be_used) - { - /* Start the flush phase. */ - keycache->resize_in_flush= 1; - - if (flush_all_key_blocks(keycache)) - { - /* TODO: if this happens, we should write a warning in the log file ! */ - keycache->resize_in_flush= 0; - blocks= 0; - keycache->can_be_used= 0; - goto finish; - } - DBUG_ASSERT(cache_empty(keycache)); - - /* End the flush phase. */ - keycache->resize_in_flush= 0; - } - - /* - Some direct read/write operations (bypassing the cache) may still be - unfinished. Wait until they are done. If the key cache can be used, - direct I/O is done in increments of key_cache_block_size. That is, - every block is checked if it is in the cache. We need to wait for - pending I/O before re-initializing the cache, because we may change - the block size. Otherwise they could check for blocks at file - positions where the new block division has none. We do also want to - wait for I/O done when (if) the cache was disabled. It must not - run in parallel with normal cache operation. - */ - while (keycache->cnt_for_resize_op) - wait_on_queue(&keycache->waiting_for_resize_cnt, &keycache->cache_lock); - - /* - Free old cache structures, allocate new structures, and initialize - them. Note that the cache_lock mutex and the resize_queue are left - untouched. We do not lose the cache_lock and will release it only at - the end of this function. - */ - end_key_cache(keycache, 0); /* Don't free mutex */ - /* The following will work even if use_mem is 0 */ - blocks= init_key_cache(keycache, key_cache_block_size, use_mem, - division_limit, age_threshold); - -finish: - /* - Mark the resize finished. This allows other threads to start a - resize or to request new cache blocks. - */ - keycache->in_resize= 0; - - /* Signal waiting threads. */ - release_whole_queue(&keycache->resize_queue); - - keycache_pthread_mutex_unlock(&keycache->cache_lock); - DBUG_RETURN(blocks); -} - - -/* - Increment counter blocking resize key cache operation -*/ -static inline void inc_counter_for_resize_op(KEY_CACHE *keycache) -{ - keycache->cnt_for_resize_op++; -} - - -/* - Decrement counter blocking resize key cache operation; - Signal the operation to proceed when counter becomes equal zero -*/ -static inline void dec_counter_for_resize_op(KEY_CACHE *keycache) -{ - if (!--keycache->cnt_for_resize_op) - release_whole_queue(&keycache->waiting_for_resize_cnt); -} - -/* - Change the key cache parameters - - SYNOPSIS - change_key_cache_param() - keycache pointer to a key cache data structure - division_limit new division limit (if not zero) - age_threshold new age threshold (if not zero) - - RETURN VALUE - none - - NOTES. - Presently the function resets the key cache parameters - concerning midpoint insertion strategy - division_limit and - age_threshold. -*/ - -void change_key_cache_param(KEY_CACHE *keycache, uint division_limit, - uint age_threshold) -{ - DBUG_ENTER("change_key_cache_param"); - - keycache_pthread_mutex_lock(&keycache->cache_lock); - if (division_limit) - keycache->min_warm_blocks= (keycache->disk_blocks * - division_limit / 100 + 1); - if (age_threshold) - keycache->age_threshold= (keycache->disk_blocks * - age_threshold / 100); - keycache_pthread_mutex_unlock(&keycache->cache_lock); - DBUG_VOID_RETURN; -} - - -/* - Remove key_cache from memory - - SYNOPSIS - end_key_cache() - keycache key cache handle - cleanup Complete free (Free also mutex for key cache) - - RETURN VALUE - none -*/ - -void end_key_cache(KEY_CACHE *keycache, my_bool cleanup) -{ - DBUG_ENTER("end_key_cache"); - DBUG_PRINT("enter", ("key_cache: 0x%lx", (long) keycache)); - - if (!keycache->key_cache_inited) - DBUG_VOID_RETURN; - - if (keycache->disk_blocks > 0) - { - if (keycache->block_mem) - { - my_large_free((uchar*) keycache->block_mem); - keycache->block_mem= NULL; - my_free(keycache->block_root); - keycache->block_root= NULL; - } - keycache->disk_blocks= -1; - /* Reset blocks_changed to be safe if flush_all_key_blocks is called */ - keycache->blocks_changed= 0; - } - - DBUG_PRINT("status", ("used: %lu changed: %lu w_requests: %lu " - "writes: %lu r_requests: %lu reads: %lu", - keycache->blocks_used, keycache->global_blocks_changed, - (ulong) keycache->global_cache_w_requests, - (ulong) keycache->global_cache_write, - (ulong) keycache->global_cache_r_requests, - (ulong) keycache->global_cache_read)); - - /* - Reset these values to be able to detect a disabled key cache. - See Bug#44068 (RESTORE can disable the MyISAM Key Cache). - */ - keycache->blocks_used= 0; - keycache->blocks_unused= 0; - - if (cleanup) - { - mysql_mutex_destroy(&keycache->cache_lock); - keycache->key_cache_inited= keycache->can_be_used= 0; - KEYCACHE_DEBUG_CLOSE; - } - DBUG_VOID_RETURN; -} /* end_key_cache */ - - -/* - Link a thread into double-linked queue of waiting threads. - - SYNOPSIS - link_into_queue() - wqueue pointer to the queue structure - thread pointer to the thread to be added to the queue - - RETURN VALUE - none - - NOTES. - Queue is represented by a circular list of the thread structures - The list is double-linked of the type (**prev,*next), accessed by - a pointer to the last element. -*/ - -static void link_into_queue(KEYCACHE_WQUEUE *wqueue, - struct st_my_thread_var *thread) -{ - struct st_my_thread_var *last; - - DBUG_ASSERT(!thread->next && !thread->prev); - if (! (last= wqueue->last_thread)) - { - /* Queue is empty */ - thread->next= thread; - thread->prev= &thread->next; - } - else - { - thread->prev= last->next->prev; - last->next->prev= &thread->next; - thread->next= last->next; - last->next= thread; - } - wqueue->last_thread= thread; -} - -/* - Unlink a thread from double-linked queue of waiting threads - - SYNOPSIS - unlink_from_queue() - wqueue pointer to the queue structure - thread pointer to the thread to be removed from the queue - - RETURN VALUE - none - - NOTES. - See NOTES for link_into_queue -*/ - -static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue, - struct st_my_thread_var *thread) -{ - KEYCACHE_DBUG_PRINT("unlink_from_queue", ("thread %ld", thread->id)); - DBUG_ASSERT(thread->next && thread->prev); - if (thread->next == thread) - /* The queue contains only one member */ - wqueue->last_thread= NULL; - else - { - thread->next->prev= thread->prev; - *thread->prev=thread->next; - if (wqueue->last_thread == thread) - wqueue->last_thread= STRUCT_PTR(struct st_my_thread_var, next, - thread->prev); - } - thread->next= NULL; -#if !defined(DBUG_OFF) - /* - This makes it easier to see it's not in a chain during debugging. - And some DBUG_ASSERT() rely on it. - */ - thread->prev= NULL; -#endif -} - - -/* - Add a thread to single-linked queue of waiting threads - - SYNOPSIS - wait_on_queue() - wqueue Pointer to the queue structure. - mutex Cache_lock to acquire after awake. - - RETURN VALUE - none - - NOTES. - Queue is represented by a circular list of the thread structures - The list is single-linked of the type (*next), accessed by a pointer - to the last element. - - The function protects against stray signals by verifying that the - current thread is unlinked from the queue when awaking. However, - since several threads can wait for the same event, it might be - necessary for the caller of the function to check again if the - condition for awake is indeed matched. -*/ - -static void wait_on_queue(KEYCACHE_WQUEUE *wqueue, - mysql_mutex_t *mutex) -{ - struct st_my_thread_var *last; - struct st_my_thread_var *thread= my_thread_var; - - /* Add to queue. */ - DBUG_ASSERT(!thread->next); - DBUG_ASSERT(!thread->prev); /* Not required, but must be true anyway. */ - if (! (last= wqueue->last_thread)) - thread->next= thread; - else - { - thread->next= last->next; - last->next= thread; - } - wqueue->last_thread= thread; - - /* - Wait until thread is removed from queue by the signalling thread. - The loop protects against stray signals. - */ - do - { - KEYCACHE_DBUG_PRINT("wait", ("suspend thread %ld", thread->id)); - keycache_pthread_cond_wait(&thread->suspend, mutex); - } - while (thread->next); -} - - -/* - Remove all threads from queue signaling them to proceed - - SYNOPSIS - release_whole_queue() - wqueue pointer to the queue structure - - RETURN VALUE - none - - NOTES. - See notes for wait_on_queue(). - When removed from the queue each thread is signaled via condition - variable thread->suspend. -*/ - -static void release_whole_queue(KEYCACHE_WQUEUE *wqueue) -{ - struct st_my_thread_var *last; - struct st_my_thread_var *next; - struct st_my_thread_var *thread; - - /* Queue may be empty. */ - if (!(last= wqueue->last_thread)) - return; - - next= last->next; - do - { - thread=next; - KEYCACHE_DBUG_PRINT("release_whole_queue: signal", - ("thread %ld", thread->id)); - /* Signal the thread. */ - keycache_pthread_cond_signal(&thread->suspend); - /* Take thread from queue. */ - next=thread->next; - thread->next= NULL; - } - while (thread != last); - - /* Now queue is definitely empty. */ - wqueue->last_thread= NULL; -} - - -/* - Unlink a block from the chain of dirty/clean blocks -*/ - -static inline void unlink_changed(BLOCK_LINK *block) -{ - DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); - if (block->next_changed) - block->next_changed->prev_changed= block->prev_changed; - *block->prev_changed= block->next_changed; - -#if !defined(DBUG_OFF) - /* - This makes it easier to see it's not in a chain during debugging. - And some DBUG_ASSERT() rely on it. - */ - block->next_changed= NULL; - block->prev_changed= NULL; -#endif -} - - -/* - Link a block into the chain of dirty/clean blocks -*/ - -static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead) -{ - DBUG_ASSERT(!block->next_changed); - DBUG_ASSERT(!block->prev_changed); - block->prev_changed= phead; - if ((block->next_changed= *phead)) - (*phead)->prev_changed= &block->next_changed; - *phead= block; -} - - -/* - Link a block in a chain of clean blocks of a file. - - SYNOPSIS - link_to_file_list() - keycache Key cache handle - block Block to relink - file File to be linked to - unlink If to unlink first - - DESCRIPTION - Unlink a block from whichever chain it is linked in, if it's - asked for, and link it to the chain of clean blocks of the - specified file. - - NOTE - Please do never set/clear BLOCK_CHANGED outside of - link_to_file_list() or link_to_changed_list(). - You would risk to damage correct counting of changed blocks - and to find blocks in the wrong hash. - - RETURN - void -*/ - -static void link_to_file_list(KEY_CACHE *keycache, - BLOCK_LINK *block, int file, - my_bool unlink_block) -{ - DBUG_ASSERT(block->status & BLOCK_IN_USE); - DBUG_ASSERT(block->hash_link && block->hash_link->block == block); - DBUG_ASSERT(block->hash_link->file == file); - if (unlink_block) - unlink_changed(block); - link_changed(block, &keycache->file_blocks[FILE_HASH(file)]); - if (block->status & BLOCK_CHANGED) - { - block->status&= ~BLOCK_CHANGED; - keycache->blocks_changed--; - keycache->global_blocks_changed--; - } -} - - -/* - Re-link a block from the clean chain to the dirty chain of a file. - - SYNOPSIS - link_to_changed_list() - keycache key cache handle - block block to relink - - DESCRIPTION - Unlink a block from the chain of clean blocks of a file - and link it to the chain of dirty blocks of the same file. - - NOTE - Please do never set/clear BLOCK_CHANGED outside of - link_to_file_list() or link_to_changed_list(). - You would risk to damage correct counting of changed blocks - and to find blocks in the wrong hash. - - RETURN - void -*/ - -static void link_to_changed_list(KEY_CACHE *keycache, - BLOCK_LINK *block) -{ - DBUG_ASSERT(block->status & BLOCK_IN_USE); - DBUG_ASSERT(!(block->status & BLOCK_CHANGED)); - DBUG_ASSERT(block->hash_link && block->hash_link->block == block); - - unlink_changed(block); - link_changed(block, - &keycache->changed_blocks[FILE_HASH(block->hash_link->file)]); - block->status|=BLOCK_CHANGED; - keycache->blocks_changed++; - keycache->global_blocks_changed++; -} - - -/* - Link a block to the LRU chain at the beginning or at the end of - one of two parts. - - SYNOPSIS - link_block() - keycache pointer to a key cache data structure - block pointer to the block to link to the LRU chain - hot <-> to link the block into the hot subchain - at_end <-> to link the block at the end of the subchain - - RETURN VALUE - none - - NOTES. - The LRU ring is represented by a circular list of block structures. - The list is double-linked of the type (**prev,*next) type. - The LRU ring is divided into two parts - hot and warm. - There are two pointers to access the last blocks of these two - parts. The beginning of the warm part follows right after the - end of the hot part. - Only blocks of the warm part can be used for eviction. - The first block from the beginning of this subchain is always - taken for eviction (keycache->last_used->next) - - LRU chain: +------+ H O T +------+ - +----| end |----...<----| beg |----+ - | +------+last +------+ | - v<-link in latest hot (new end) | - | link in latest warm (new end)->^ - | +------+ W A R M +------+ | - +----| beg |---->...----| end |----+ - +------+ +------+ins - first for eviction - - It is also possible that the block is selected for eviction and thus - not linked in the LRU ring. -*/ - -static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot, - my_bool at_end) -{ - BLOCK_LINK *ins; - BLOCK_LINK **pins; - - DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE)); - DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/ - DBUG_ASSERT(!block->requests); - DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); - DBUG_ASSERT(!block->next_used); - DBUG_ASSERT(!block->prev_used); - - if (!hot && keycache->waiting_for_block.last_thread) - { - /* Signal that in the LRU warm sub-chain an available block has appeared */ - struct st_my_thread_var *last_thread= - keycache->waiting_for_block.last_thread; - struct st_my_thread_var *first_thread= last_thread->next; - struct st_my_thread_var *next_thread= first_thread; - HASH_LINK *hash_link= (HASH_LINK *) first_thread->opt_info; - struct st_my_thread_var *thread; - do - { - thread= next_thread; - next_thread= thread->next; - /* - We notify about the event all threads that ask - for the same page as the first thread in the queue - */ - if ((HASH_LINK *) thread->opt_info == hash_link) - { - KEYCACHE_DBUG_PRINT("link_block: signal", ("thread %ld", thread->id)); - keycache_pthread_cond_signal(&thread->suspend); - unlink_from_queue(&keycache->waiting_for_block, thread); - block->requests++; - } - } - while (thread != last_thread); - hash_link->block= block; - /* - NOTE: We assigned the block to the hash_link and signalled the - requesting thread(s). But it is possible that other threads runs - first. These threads see the hash_link assigned to a block which - is assigned to another hash_link and not marked BLOCK_IN_SWITCH. - This can be a problem for functions that do not select the block - via its hash_link: flush and free. They do only see a block which - is in a "normal" state and don't know that it will be evicted soon. - - We cannot set BLOCK_IN_SWITCH here because only one of the - requesting threads must handle the eviction. All others must wait - for it to complete. If we set the flag here, the threads would not - know who is in charge of the eviction. Without the flag, the first - thread takes the stick and sets the flag. - - But we need to note in the block that is has been selected for - eviction. It must not be freed. The evicting thread will not - expect the block in the free list. Before freeing we could also - check if block->requests > 1. But I think including another flag - in the check of block->status is slightly more efficient and - probably easier to read. - */ - block->status|= BLOCK_IN_EVICTION; - KEYCACHE_THREAD_TRACE("link_block: after signaling"); -#if defined(KEYCACHE_DEBUG) - KEYCACHE_DBUG_PRINT("link_block", - ("linked,unlinked block %u status=%x #requests=%u #available=%u", - BLOCK_NUMBER(block), block->status, - block->requests, keycache->blocks_available)); -#endif - return; - } - - pins= hot ? &keycache->used_ins : &keycache->used_last; - ins= *pins; - if (ins) - { - ins->next_used->prev_used= &block->next_used; - block->next_used= ins->next_used; - block->prev_used= &ins->next_used; - ins->next_used= block; - if (at_end) - *pins= block; - } - else - { - /* The LRU ring is empty. Let the block point to itself. */ - keycache->used_last= keycache->used_ins= block->next_used= block; - block->prev_used= &block->next_used; - } - KEYCACHE_THREAD_TRACE("link_block"); -#if defined(KEYCACHE_DEBUG) - keycache->blocks_available++; - KEYCACHE_DBUG_PRINT("link_block", - ("linked block %u:%1u status=%x #requests=%u #available=%u", - BLOCK_NUMBER(block), at_end, block->status, - block->requests, keycache->blocks_available)); - KEYCACHE_DBUG_ASSERT((ulong) keycache->blocks_available <= - keycache->blocks_used); -#endif -} - - -/* - Unlink a block from the LRU chain - - SYNOPSIS - unlink_block() - keycache pointer to a key cache data structure - block pointer to the block to unlink from the LRU chain - - RETURN VALUE - none - - NOTES. - See NOTES for link_block -*/ - -static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block) -{ - DBUG_ASSERT((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE)); - DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/ - DBUG_ASSERT(!block->requests); - DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); - DBUG_ASSERT(block->next_used && block->prev_used && - (block->next_used->prev_used == &block->next_used) && - (*block->prev_used == block)); - if (block->next_used == block) - /* The list contains only one member */ - keycache->used_last= keycache->used_ins= NULL; - else - { - block->next_used->prev_used= block->prev_used; - *block->prev_used= block->next_used; - if (keycache->used_last == block) - keycache->used_last= STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used); - if (keycache->used_ins == block) - keycache->used_ins=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used); - } - block->next_used= NULL; -#if !defined(DBUG_OFF) - /* - This makes it easier to see it's not in a chain during debugging. - And some DBUG_ASSERT() rely on it. - */ - block->prev_used= NULL; -#endif - - KEYCACHE_THREAD_TRACE("unlink_block"); -#if defined(KEYCACHE_DEBUG) - KEYCACHE_DBUG_ASSERT(keycache->blocks_available != 0); - keycache->blocks_available--; - KEYCACHE_DBUG_PRINT("unlink_block", - ("unlinked block %u status=%x #requests=%u #available=%u", - BLOCK_NUMBER(block), block->status, - block->requests, keycache->blocks_available)); -#endif -} - - -/* - Register requests for a block. - - SYNOPSIS - reg_requests() - keycache Pointer to a key cache data structure. - block Pointer to the block to register a request on. - count Number of requests. Always 1. - - NOTE - The first request unlinks the block from the LRU ring. This means - that it is protected against eveiction. - - RETURN - void -*/ -static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count) -{ - DBUG_ASSERT(block->status & BLOCK_IN_USE); - DBUG_ASSERT(block->hash_link); - - if (!block->requests) - unlink_block(keycache, block); - block->requests+=count; -} - - -/* - Unregister request for a block - linking it to the LRU chain if it's the last request - - SYNOPSIS - unreg_request() - keycache pointer to a key cache data structure - block pointer to the block to link to the LRU chain - at_end <-> to link the block at the end of the LRU chain - - RETURN VALUE - none - - NOTES. - Every linking to the LRU ring decrements by one a special block - counter (if it's positive). If the at_end parameter is TRUE the block is - added either at the end of warm sub-chain or at the end of hot sub-chain. - It is added to the hot subchain if its counter is zero and number of - blocks in warm sub-chain is not less than some low limit (determined by - the division_limit parameter). Otherwise the block is added to the warm - sub-chain. If the at_end parameter is FALSE the block is always added - at beginning of the warm sub-chain. - Thus a warm block can be promoted to the hot sub-chain when its counter - becomes zero for the first time. - At the same time the block at the very beginning of the hot subchain - might be moved to the beginning of the warm subchain if it stays untouched - for a too long time (this time is determined by parameter age_threshold). - - It is also possible that the block is selected for eviction and thus - not linked in the LRU ring. -*/ - -static void unreg_request(KEY_CACHE *keycache, - BLOCK_LINK *block, int at_end) -{ - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - DBUG_ASSERT(block->hash_link); /*backptr to block NULL from free_block()*/ - DBUG_ASSERT(block->requests); - DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); - DBUG_ASSERT(!block->next_used); - DBUG_ASSERT(!block->prev_used); - /* - Unregister the request, but do not link erroneous blocks into the - LRU ring. - */ - if (!--block->requests && !(block->status & BLOCK_ERROR)) - { - my_bool hot; - if (block->hits_left) - block->hits_left--; - hot= !block->hits_left && at_end && - keycache->warm_blocks > keycache->min_warm_blocks; - if (hot) - { - if (block->temperature == BLOCK_WARM) - keycache->warm_blocks--; - block->temperature= BLOCK_HOT; - KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu", - keycache->warm_blocks)); - } - link_block(keycache, block, hot, (my_bool)at_end); - block->last_hit_time= keycache->keycache_time; - keycache->keycache_time++; - /* - At this place, the block might be in the LRU ring or not. If an - evicter was waiting for a block, it was selected for eviction and - not linked in the LRU ring. - */ - - /* - Check if we should link a hot block to the warm block sub-chain. - It is possible that we select the same block as above. But it can - also be another block. In any case a block from the LRU ring is - selected. In other words it works even if the above block was - selected for eviction and not linked in the LRU ring. Since this - happens only if the LRU ring is empty, the block selected below - would be NULL and the rest of the function skipped. - */ - block= keycache->used_ins; - if (block && keycache->keycache_time - block->last_hit_time > - keycache->age_threshold) - { - unlink_block(keycache, block); - link_block(keycache, block, 0, 0); - if (block->temperature != BLOCK_WARM) - { - keycache->warm_blocks++; - block->temperature= BLOCK_WARM; - } - KEYCACHE_DBUG_PRINT("unreg_request", ("#warm_blocks: %lu", - keycache->warm_blocks)); - } - } -} - -/* - Remove a reader of the page in block -*/ - -static void remove_reader(BLOCK_LINK *block) -{ - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - DBUG_ASSERT(block->hash_link && block->hash_link->block == block); - DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); - DBUG_ASSERT(!block->next_used); - DBUG_ASSERT(!block->prev_used); - DBUG_ASSERT(block->hash_link->requests); - - if (! --block->hash_link->requests && block->condvar) - keycache_pthread_cond_signal(block->condvar); -} - - -/* - Wait until the last reader of the page in block - signals on its termination -*/ - -static void wait_for_readers(KEY_CACHE *keycache, - BLOCK_LINK *block) -{ - struct st_my_thread_var *thread= my_thread_var; - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - DBUG_ASSERT(!(block->status & (BLOCK_IN_FLUSH | BLOCK_CHANGED))); - DBUG_ASSERT(block->hash_link); - DBUG_ASSERT(block->hash_link->block == block); - /* Linked in file_blocks or changed_blocks hash. */ - DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); - /* Not linked in LRU ring. */ - DBUG_ASSERT(!block->next_used); - DBUG_ASSERT(!block->prev_used); - while (block->hash_link->requests) - { - KEYCACHE_DBUG_PRINT("wait_for_readers: wait", - ("suspend thread %ld block %u", - thread->id, BLOCK_NUMBER(block))); - /* There must be no other waiter. We have no queue here. */ - DBUG_ASSERT(!block->condvar); - block->condvar= &thread->suspend; - keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock); - block->condvar= NULL; - } -} - - -/* - Add a hash link to a bucket in the hash_table -*/ - -static inline void link_hash(HASH_LINK **start, HASH_LINK *hash_link) -{ - if (*start) - (*start)->prev= &hash_link->next; - hash_link->next= *start; - hash_link->prev= start; - *start= hash_link; -} - - -/* - Remove a hash link from the hash table -*/ - -static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link) -{ - KEYCACHE_DBUG_PRINT("unlink_hash", ("fd: %u pos_ %lu #requests=%u", - (uint) hash_link->file,(ulong) hash_link->diskpos, hash_link->requests)); - KEYCACHE_DBUG_ASSERT(hash_link->requests == 0); - if ((*hash_link->prev= hash_link->next)) - hash_link->next->prev= hash_link->prev; - hash_link->block= NULL; - - if (keycache->waiting_for_hash_link.last_thread) - { - /* Signal that a free hash link has appeared */ - struct st_my_thread_var *last_thread= - keycache->waiting_for_hash_link.last_thread; - struct st_my_thread_var *first_thread= last_thread->next; - struct st_my_thread_var *next_thread= first_thread; - KEYCACHE_PAGE *first_page= (KEYCACHE_PAGE *) (first_thread->opt_info); - struct st_my_thread_var *thread; - - hash_link->file= first_page->file; - hash_link->diskpos= first_page->filepos; - do - { - KEYCACHE_PAGE *page; - thread= next_thread; - page= (KEYCACHE_PAGE *) thread->opt_info; - next_thread= thread->next; - /* - We notify about the event all threads that ask - for the same page as the first thread in the queue - */ - if (page->file == hash_link->file && page->filepos == hash_link->diskpos) - { - KEYCACHE_DBUG_PRINT("unlink_hash: signal", ("thread %ld", thread->id)); - keycache_pthread_cond_signal(&thread->suspend); - unlink_from_queue(&keycache->waiting_for_hash_link, thread); - } - } - while (thread != last_thread); - link_hash(&keycache->hash_root[KEYCACHE_HASH(hash_link->file, - hash_link->diskpos)], - hash_link); - return; - } - hash_link->next= keycache->free_hash_list; - keycache->free_hash_list= hash_link; -} - - -/* - Get the hash link for a page -*/ - -static HASH_LINK *get_hash_link(KEY_CACHE *keycache, - int file, my_off_t filepos) -{ - reg1 HASH_LINK *hash_link, **start; -#if defined(KEYCACHE_DEBUG) - int cnt; -#endif - - KEYCACHE_DBUG_PRINT("get_hash_link", ("fd: %u pos: %lu", - (uint) file,(ulong) filepos)); - -restart: - /* - Find the bucket in the hash table for the pair (file, filepos); - start contains the head of the bucket list, - hash_link points to the first member of the list - */ - hash_link= *(start= &keycache->hash_root[KEYCACHE_HASH(file, filepos)]); -#if defined(KEYCACHE_DEBUG) - cnt= 0; -#endif - /* Look for an element for the pair (file, filepos) in the bucket chain */ - while (hash_link && - (hash_link->diskpos != filepos || hash_link->file != file)) - { - hash_link= hash_link->next; -#if defined(KEYCACHE_DEBUG) - cnt++; - if (! (cnt <= keycache->hash_links_used)) - { - int i; - for (i=0, hash_link= *start ; - i < cnt ; i++, hash_link= hash_link->next) - { - KEYCACHE_DBUG_PRINT("get_hash_link", ("fd: %u pos: %lu", - (uint) hash_link->file,(ulong) hash_link->diskpos)); - } - } - KEYCACHE_DBUG_ASSERT(cnt <= keycache->hash_links_used); -#endif - } - if (! hash_link) - { - /* There is no hash link in the hash table for the pair (file, filepos) */ - if (keycache->free_hash_list) - { - hash_link= keycache->free_hash_list; - keycache->free_hash_list= hash_link->next; - } - else if (keycache->hash_links_used < keycache->hash_links) - { - hash_link= &keycache->hash_link_root[keycache->hash_links_used++]; - } - else - { - /* 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; - thread->opt_info= (void *) &page; - link_into_queue(&keycache->waiting_for_hash_link, thread); - KEYCACHE_DBUG_PRINT("get_hash_link: wait", - ("suspend thread %ld", thread->id)); - keycache_pthread_cond_wait(&thread->suspend, - &keycache->cache_lock); - thread->opt_info= NULL; - goto restart; - } - hash_link->file= file; - hash_link->diskpos= filepos; - link_hash(start, hash_link); - } - /* Register the request for the page */ - hash_link->requests++; - - return hash_link; -} - - -/* - Get a block for the file page requested by a keycache read/write operation; - If the page is not in the cache return a free block, if there is none - return the lru block after saving its buffer if the page is dirty. - - SYNOPSIS - - find_key_block() - keycache pointer to a key cache data structure - file handler for the file to read page from - filepos position of the page in the file - init_hits_left how initialize the block counter for the page - wrmode <-> get for writing - page_st out {PAGE_READ,PAGE_TO_BE_READ,PAGE_WAIT_TO_BE_READ} - - RETURN VALUE - Pointer to the found block if successful, 0 - otherwise - - NOTES. - For the page from file positioned at filepos the function checks whether - the page is in the key cache specified by the first parameter. - If this is the case it immediately returns the block. - If not, the function first chooses a block for this page. If there is - no not used blocks in the key cache yet, the function takes the block - at the very beginning of the warm sub-chain. It saves the page in that - block if it's dirty before returning the pointer to it. - The function returns in the page_st parameter the following values: - PAGE_READ - if page already in the block, - PAGE_TO_BE_READ - if it is to be read yet by the current thread - WAIT_TO_BE_READ - if it is to be read by another thread - If an error occurs THE BLOCK_ERROR bit is set in the block status. - It might happen that there are no blocks in LRU chain (in warm part) - - all blocks are unlinked for some read/write operations. Then the function - waits until first of this operations links any block back. -*/ - -static BLOCK_LINK *find_key_block(KEY_CACHE *keycache, - File file, my_off_t filepos, - int init_hits_left, - int wrmode, int *page_st) -{ - HASH_LINK *hash_link; - BLOCK_LINK *block; - int error= 0; - int page_status; - - DBUG_ENTER("find_key_block"); - KEYCACHE_THREAD_TRACE("find_key_block:begin"); - DBUG_PRINT("enter", ("fd: %d pos: %lu wrmode: %d", - file, (ulong) filepos, wrmode)); - KEYCACHE_DBUG_PRINT("find_key_block", ("fd: %d pos: %lu wrmode: %d", - file, (ulong) filepos, - wrmode)); -#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) - DBUG_EXECUTE("check_keycache2", - test_key_cache(keycache, "start of find_key_block", 0);); -#endif - -restart: - /* - If the flush phase of a resize operation fails, the cache is left - unusable. This will be detected only after "goto restart". - */ - if (!keycache->can_be_used) - DBUG_RETURN(0); - - /* - Find the hash_link for the requested file block (file, filepos). We - do always get a hash_link here. It has registered our request so - that no other thread can use it for another file block until we - release the request (which is done by remove_reader() usually). The - hash_link can have a block assigned to it or not. If there is a - block, it may be assigned to this hash_link or not. In cases where a - block is evicted from the cache, it is taken from the LRU ring and - referenced by the new hash_link. But the block can still be assigned - to its old hash_link for some time if it needs to be flushed first, - or if there are other threads still reading it. - - Summary: - hash_link is always returned. - hash_link->block can be: - - NULL or - - not assigned to this hash_link or - - assigned to this hash_link. If assigned, the block can have - - invalid data (when freshly assigned) or - - valid data. Valid data can be - - changed over the file contents (dirty) or - - not changed (clean). - */ - hash_link= get_hash_link(keycache, file, filepos); - DBUG_ASSERT((hash_link->file == file) && (hash_link->diskpos == filepos)); - - page_status= -1; - if ((block= hash_link->block) && - block->hash_link == hash_link && (block->status & BLOCK_READ)) - { - /* Assigned block with valid (changed or unchanged) contents. */ - page_status= PAGE_READ; - } - /* - else (page_status == -1) - - block == NULL or - - block not assigned to this hash_link or - - block assigned but not yet read from file (invalid data). - */ - - if (keycache->in_resize) - { - /* This is a request during a resize operation */ - - if (!block) - { - struct st_my_thread_var *thread; - - /* - The file block is not in the cache. We don't need it in the - cache: we are going to read or write directly to file. Cancel - the request. We can simply decrement hash_link->requests because - we did not release cache_lock since increasing it. So no other - thread can wait for our request to become released. - */ - if (hash_link->requests == 1) - { - /* - We are the only one to request this hash_link (this file/pos). - Free the hash_link. - */ - hash_link->requests--; - unlink_hash(keycache, hash_link); - DBUG_RETURN(0); - } - - /* - More requests on the hash_link. Someone tries to evict a block - for this hash_link (could have started before resizing started). - This means that the LRU ring is empty. Otherwise a block could - be assigned immediately. Behave like a thread that wants to - evict a block for this file/pos. Add to the queue of threads - waiting for a block. Wait until there is one assigned. - - Refresh the request on the hash-link so that it cannot be reused - for another file/pos. - */ - thread= my_thread_var; - thread->opt_info= (void *) hash_link; - link_into_queue(&keycache->waiting_for_block, thread); - do - { - KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); - keycache_pthread_cond_wait(&thread->suspend, - &keycache->cache_lock); - } while (thread->next); - thread->opt_info= NULL; - /* - A block should now be assigned to the hash_link. But it may - still need to be evicted. Anyway, we should re-check the - situation. page_status must be set correctly. - */ - hash_link->requests--; - goto restart; - } /* end of if (!block) */ - - /* - There is a block for this file/pos in the cache. Register a - request on it. This unlinks it from the LRU ring (if it is there) - and hence protects it against eviction (if not already in - eviction). We need this for returning the block to the caller, for - calling remove_reader() (for debugging purposes), and for calling - free_block(). The only case where we don't need the request is if - the block is in eviction. In that case we have to unregister the - request later. - */ - reg_requests(keycache, block, 1); - - if (page_status != PAGE_READ) - { - /* - - block not assigned to this hash_link or - - block assigned but not yet read from file (invalid data). - - This must be a block in eviction. It will be read soon. We need - to wait here until this happened. Otherwise the caller could - access a wrong block or a block which is in read. While waiting - we cannot lose hash_link nor block. We have registered a request - on the hash_link. Everything can happen to the block but changes - in the hash_link -> block relationship. In other words: - everything can happen to the block but free or another completed - eviction. - - Note that we bahave like a secondary requestor here. We just - cannot return with PAGE_WAIT_TO_BE_READ. This would work for - read requests and writes on dirty blocks that are not in flush - only. Waiting here on COND_FOR_REQUESTED works in all - situations. - */ - DBUG_ASSERT(((block->hash_link != hash_link) && - (block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))) || - ((block->hash_link == hash_link) && - !(block->status & BLOCK_READ))); - wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock); - /* - Here we can trust that the block has been assigned to this - hash_link (block->hash_link == hash_link) and read into the - buffer (BLOCK_READ). The worst things possible here are that the - block is in free (BLOCK_REASSIGNED). But the block is still - assigned to the hash_link. The freeing thread waits until we - release our request on the hash_link. The block must not be - again in eviction because we registered an request on it before - starting to wait. - */ - DBUG_ASSERT(block->hash_link == hash_link); - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - DBUG_ASSERT(!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))); - } - /* - The block is in the cache. Assigned to the hash_link. Valid data. - Note that in case of page_st == PAGE_READ, the block can be marked - for eviction. In any case it can be marked for freeing. - */ - - if (!wrmode) - { - /* A reader can just read the block. */ - *page_st= PAGE_READ; - DBUG_ASSERT((hash_link->file == file) && - (hash_link->diskpos == filepos) && - (block->hash_link == hash_link)); - DBUG_RETURN(block); - } - - /* - This is a writer. No two writers for the same block can exist. - This must be assured by locks outside of the key cache. - */ - DBUG_ASSERT(!(block->status & BLOCK_FOR_UPDATE) || fail_block(block)); - - while (block->status & BLOCK_IN_FLUSH) - { - /* - Wait until the block is flushed to file. Do not release the - request on the hash_link yet to prevent that the block is freed - or reassigned while we wait. While we wait, several things can - happen to the block, including another flush. But the block - cannot be reassigned to another hash_link until we release our - request on it. But it can be marked BLOCK_REASSIGNED from free - or eviction, while they wait for us to release the hash_link. - */ - wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock); - /* - If the flush phase failed, the resize could have finished while - we waited here. - */ - if (!keycache->in_resize) - { - remove_reader(block); - unreg_request(keycache, block, 1); - goto restart; - } - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - DBUG_ASSERT(!(block->status & BLOCK_FOR_UPDATE) || fail_block(block)); - DBUG_ASSERT(block->hash_link == hash_link); - } - - if (block->status & BLOCK_CHANGED) - { - /* - We want to write a block with changed contents. If the cache - block size is bigger than the callers block size (e.g. MyISAM), - the caller may replace part of the block only. Changes of the - other part of the block must be preserved. Since the block has - not yet been selected for flush, we can still add our changes. - */ - *page_st= PAGE_READ; - DBUG_ASSERT((hash_link->file == file) && - (hash_link->diskpos == filepos) && - (block->hash_link == hash_link)); - DBUG_RETURN(block); - } - - /* - This is a write request for a clean block. We do not want to have - new dirty blocks in the cache while resizing. We will free the - block and write directly to file. If the block is in eviction or - in free, we just let it go. - - Unregister from the hash_link. This must be done before freeing - the block. And it must be done if not freeing the block. Because - we could have waited above, we need to call remove_reader(). Other - threads could wait for us to release our request on the hash_link. - */ - remove_reader(block); - - /* If the block is not in eviction and not in free, we can free it. */ - if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | - BLOCK_REASSIGNED))) - { - /* - Free block as we are going to write directly to file. - Although we have an exlusive lock for the updated key part, - the control can be yielded by the current thread as we might - have unfinished readers of other key parts in the block - buffer. Still we are guaranteed not to have any readers - of the key part we are writing into until the block is - removed from the cache as we set the BLOCK_REASSIGNED - flag (see the code below that handles reading requests). - */ - free_block(keycache, block); - } - else - { - /* - The block will be evicted/freed soon. Don't touch it in any way. - Unregister the request that we registered above. - */ - unreg_request(keycache, block, 1); - - /* - The block is still assigned to the hash_link (the file/pos that - we are going to write to). Wait until the eviction/free is - complete. Otherwise the direct write could complete before all - readers are done with the block. So they could read outdated - data. - - Since we released our request on the hash_link, it can be reused - for another file/pos. Hence we cannot just check for - block->hash_link == hash_link. As long as the resize is - proceeding the block cannot be reassigned to the same file/pos - again. So we can terminate the loop when the block is no longer - assigned to this file/pos. - */ - do - { - wait_on_queue(&block->wqueue[COND_FOR_SAVED], - &keycache->cache_lock); - /* - If the flush phase failed, the resize could have finished - while we waited here. - */ - if (!keycache->in_resize) - goto restart; - } while (block->hash_link && - (block->hash_link->file == file) && - (block->hash_link->diskpos == filepos)); - } - DBUG_RETURN(0); - } - - if (page_status == PAGE_READ && - (block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | - BLOCK_REASSIGNED))) - { - /* - This is a request for a block to be removed from cache. The block - is assigned to this hash_link and contains valid data, but is - marked for eviction or to be freed. Possible reasons why it has - not yet been evicted/freed can be a flush before reassignment - (BLOCK_IN_SWITCH), readers of the block have not finished yet - (BLOCK_REASSIGNED), or the evicting thread did not yet awake after - the block has been selected for it (BLOCK_IN_EVICTION). - */ - - KEYCACHE_DBUG_PRINT("find_key_block", - ("request for old page in block %u " - "wrmode: %d block->status: %d", - BLOCK_NUMBER(block), wrmode, block->status)); - /* - Only reading requests can proceed until the old dirty page is flushed, - all others are to be suspended, then resubmitted - */ - if (!wrmode && !(block->status & BLOCK_REASSIGNED)) - { - /* - This is a read request and the block not yet reassigned. We can - register our request and proceed. This unlinks the block from - the LRU ring and protects it against eviction. - */ - reg_requests(keycache, block, 1); - } - else - { - /* - Either this is a write request for a block that is in eviction - or in free. We must not use it any more. Instead we must evict - another block. But we cannot do this before the eviction/free is - done. Otherwise we would find the same hash_link + block again - and again. - - Or this is a read request for a block in eviction/free that does - not require a flush, but waits for readers to finish with the - block. We do not read this block to let the eviction/free happen - as soon as possible. Again we must wait so that we don't find - the same hash_link + block again and again. - */ - DBUG_ASSERT(hash_link->requests); - hash_link->requests--; - KEYCACHE_DBUG_PRINT("find_key_block", - ("request waiting for old page to be saved")); - wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock); - KEYCACHE_DBUG_PRINT("find_key_block", - ("request for old page resubmitted")); - /* - The block is no longer assigned to this hash_link. - Get another one. - */ - goto restart; - } - } - else - { - /* - This is a request for a new block or for a block not to be removed. - Either - - block == NULL or - - block not assigned to this hash_link or - - block assigned but not yet read from file, - or - - block assigned with valid (changed or unchanged) data and - - it will not be reassigned/freed. - */ - if (! block) - { - /* No block is assigned to the hash_link yet. */ - if (keycache->blocks_unused) - { - if (keycache->free_block_list) - { - /* There is a block in the free list. */ - block= keycache->free_block_list; - keycache->free_block_list= block->next_used; - block->next_used= NULL; - } - else - { - size_t block_mem_offset; - /* There are some never used blocks, take first of them */ - DBUG_ASSERT(keycache->blocks_used < - (ulong) keycache->disk_blocks); - block= &keycache->block_root[keycache->blocks_used]; - block_mem_offset= - ((size_t) keycache->blocks_used) * keycache->key_cache_block_size; - block->buffer= ADD_TO_PTR(keycache->block_mem, - block_mem_offset, - uchar*); - keycache->blocks_used++; - DBUG_ASSERT(!block->next_used); - } - DBUG_ASSERT(!block->prev_used); - DBUG_ASSERT(!block->next_changed); - DBUG_ASSERT(!block->prev_changed); - DBUG_ASSERT(!block->hash_link); - DBUG_ASSERT(!block->status); - DBUG_ASSERT(!block->requests); - keycache->blocks_unused--; - block->status= BLOCK_IN_USE; - block->length= 0; - block->offset= keycache->key_cache_block_size; - block->requests= 1; - block->temperature= BLOCK_COLD; - block->hits_left= init_hits_left; - block->last_hit_time= 0; - block->hash_link= hash_link; - hash_link->block= block; - link_to_file_list(keycache, block, file, 0); - page_status= PAGE_TO_BE_READ; - KEYCACHE_DBUG_PRINT("find_key_block", - ("got free or never used block %u", - BLOCK_NUMBER(block))); - } - else - { - /* - There are no free blocks and no never used blocks, use a block - from the LRU ring. - */ - - if (! keycache->used_last) - { - /* - The LRU ring is empty. Wait until a new block is added to - it. Several threads might wait here for the same hash_link, - all of them must get the same block. While waiting for a - block, after a block is selected for this hash_link, other - threads can run first before this one awakes. During this - time interval other threads find this hash_link pointing to - the block, which is still assigned to another hash_link. In - this case the block is not marked BLOCK_IN_SWITCH yet, but - it is marked BLOCK_IN_EVICTION. - */ - - struct st_my_thread_var *thread= my_thread_var; - thread->opt_info= (void *) hash_link; - link_into_queue(&keycache->waiting_for_block, thread); - do - { - KEYCACHE_DBUG_PRINT("find_key_block: wait", - ("suspend thread %ld", thread->id)); - keycache_pthread_cond_wait(&thread->suspend, - &keycache->cache_lock); - } - while (thread->next); - thread->opt_info= NULL; - /* Assert that block has a request registered. */ - DBUG_ASSERT(hash_link->block->requests); - /* Assert that block is not in LRU ring. */ - DBUG_ASSERT(!hash_link->block->next_used); - DBUG_ASSERT(!hash_link->block->prev_used); - } - - /* - If we waited above, hash_link->block has been assigned by - link_block(). Otherwise it is still NULL. In the latter case - we need to grab a block from the LRU ring ourselves. - */ - block= hash_link->block; - if (! block) - { - /* Select the last block from the LRU ring. */ - block= keycache->used_last->next_used; - block->hits_left= init_hits_left; - block->last_hit_time= 0; - hash_link->block= block; - /* - Register a request on the block. This unlinks it from the - LRU ring and protects it against eviction. - */ - DBUG_ASSERT(!block->requests); - reg_requests(keycache, block,1); - /* - We do not need to set block->status|= BLOCK_IN_EVICTION here - because we will set block->status|= BLOCK_IN_SWITCH - immediately without releasing the lock in between. This does - also support debugging. When looking at the block, one can - see if the block has been selected by link_block() after the - LRU ring was empty, or if it was grabbed directly from the - LRU ring in this branch. - */ - } - - /* - If we had to wait above, there is a small chance that another - thread grabbed this block for the same file block already. But - in most cases the first condition is true. - */ - if (block->hash_link != hash_link && - ! (block->status & BLOCK_IN_SWITCH) ) - { - /* this is a primary request for a new page */ - block->status|= BLOCK_IN_SWITCH; - - KEYCACHE_DBUG_PRINT("find_key_block", - ("got block %u for new page", BLOCK_NUMBER(block))); - - if (block->status & BLOCK_CHANGED) - { - /* The block contains a dirty page - push it out of the cache */ - - KEYCACHE_DBUG_PRINT("find_key_block", ("block is dirty")); - if (block->status & BLOCK_IN_FLUSH) - { - /* - The block is marked for flush. If we do not wait here, - it could happen that we write the block, reassign it to - another file block, then, before the new owner can read - the new file block, the flusher writes the cache block - (which still has the old contents) to the new file block! - */ - wait_on_queue(&block->wqueue[COND_FOR_SAVED], - &keycache->cache_lock); - /* - The block is marked BLOCK_IN_SWITCH. It should be left - alone except for reading. No free, no write. - */ - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - DBUG_ASSERT(!(block->status & (BLOCK_REASSIGNED | - BLOCK_CHANGED | - BLOCK_FOR_UPDATE))); - } - else - { - block->status|= BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE; - /* - BLOCK_IN_EVICTION may be true or not. Other flags must - have a fixed value. - */ - DBUG_ASSERT((block->status & ~BLOCK_IN_EVICTION) == - (BLOCK_READ | BLOCK_IN_SWITCH | - BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE | - BLOCK_CHANGED | BLOCK_IN_USE)); - DBUG_ASSERT(block->hash_link); - - keycache_pthread_mutex_unlock(&keycache->cache_lock); - /* - The call is thread safe because only the current - thread might change the block->hash_link value - */ - error= my_pwrite(block->hash_link->file, - block->buffer + block->offset, - block->length - block->offset, - block->hash_link->diskpos + block->offset, - MYF(MY_NABP | MY_WAIT_IF_FULL)); - keycache_pthread_mutex_lock(&keycache->cache_lock); - - /* Block status must not have changed. */ - DBUG_ASSERT((block->status & ~BLOCK_IN_EVICTION) == - (BLOCK_READ | BLOCK_IN_SWITCH | - BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE | - BLOCK_CHANGED | BLOCK_IN_USE) || fail_block(block)); - keycache->global_cache_write++; - } - } - - block->status|= BLOCK_REASSIGNED; - /* - The block comes from the LRU ring. It must have a hash_link - assigned. - */ - DBUG_ASSERT(block->hash_link); - if (block->hash_link) - { - /* - All pending requests for this page must be resubmitted. - This must be done before waiting for readers. They could - wait for the flush to complete. And we must also do it - after the wait. Flushers might try to free the block while - we wait. They would wait until the reassignment is - complete. Also the block status must reflect the correct - situation: The block is not changed nor in flush any more. - Note that we must not change the BLOCK_CHANGED flag - outside of link_to_file_list() so that it is always in the - correct queue and the *blocks_changed counters are - correct. - */ - block->status&= ~(BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE); - link_to_file_list(keycache, block, block->hash_link->file, 1); - release_whole_queue(&block->wqueue[COND_FOR_SAVED]); - /* - The block is still assigned to its old hash_link. - Wait until all pending read requests - for this page are executed - (we could have avoided this waiting, if we had read - a page in the cache in a sweep, without yielding control) - */ - wait_for_readers(keycache, block); - DBUG_ASSERT(block->hash_link && block->hash_link->block == block && - block->prev_changed); - /* The reader must not have been a writer. */ - DBUG_ASSERT(!(block->status & BLOCK_CHANGED)); - - /* Wake flushers that might have found the block in between. */ - release_whole_queue(&block->wqueue[COND_FOR_SAVED]); - - /* Remove the hash link for the old file block from the hash. */ - unlink_hash(keycache, block->hash_link); - - /* - For sanity checks link_to_file_list() asserts that block - and hash_link refer to each other. Hence we need to assign - the hash_link first, but then we would not know if it was - linked before. Hence we would not know if to unlink it. So - unlink it here and call link_to_file_list(..., FALSE). - */ - unlink_changed(block); - } - block->status= error ? BLOCK_ERROR : BLOCK_IN_USE ; - block->length= 0; - block->offset= keycache->key_cache_block_size; - block->hash_link= hash_link; - link_to_file_list(keycache, block, file, 0); - page_status= PAGE_TO_BE_READ; - - KEYCACHE_DBUG_ASSERT(block->hash_link->block == block); - KEYCACHE_DBUG_ASSERT(hash_link->block->hash_link == hash_link); - } - else - { - /* - Either (block->hash_link == hash_link), - or (block->status & BLOCK_IN_SWITCH). - - This is for secondary requests for a new file block only. - Either it is already assigned to the new hash_link meanwhile - (if we had to wait due to empty LRU), or it is already in - eviction by another thread. Since this block has been - grabbed from the LRU ring and attached to this hash_link, - another thread cannot grab the same block from the LRU ring - anymore. If the block is in eviction already, it must become - attached to the same hash_link and as such destined for the - same file block. - */ - KEYCACHE_DBUG_PRINT("find_key_block", - ("block->hash_link: %p hash_link: %p " - "block->status: %u", block->hash_link, - hash_link, block->status )); - page_status= (((block->hash_link == hash_link) && - (block->status & BLOCK_READ)) ? - PAGE_READ : PAGE_WAIT_TO_BE_READ); - } - } - } - else - { - /* - Block is not NULL. This hash_link points to a block. - Either - - block not assigned to this hash_link (yet) or - - block assigned but not yet read from file, - or - - block assigned with valid (changed or unchanged) data and - - it will not be reassigned/freed. - - The first condition means hash_link points to a block in - eviction. This is not necessarily marked by BLOCK_IN_SWITCH yet. - But then it is marked BLOCK_IN_EVICTION. See the NOTE in - link_block(). In both cases it is destined for this hash_link - and its file block address. When this hash_link got its block - address, the block was removed from the LRU ring and cannot be - selected for eviction (for another hash_link) again. - - Register a request on the block. This is another protection - against eviction. - */ - DBUG_ASSERT(((block->hash_link != hash_link) && - (block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))) || - ((block->hash_link == hash_link) && - !(block->status & BLOCK_READ)) || - ((block->status & BLOCK_READ) && - !(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH)))); - reg_requests(keycache, block, 1); - KEYCACHE_DBUG_PRINT("find_key_block", - ("block->hash_link: %p hash_link: %p " - "block->status: %u", block->hash_link, - hash_link, block->status )); - page_status= (((block->hash_link == hash_link) && - (block->status & BLOCK_READ)) ? - PAGE_READ : PAGE_WAIT_TO_BE_READ); - } - } - - KEYCACHE_DBUG_ASSERT(page_status != -1); - /* Same assert basically, but be very sure. */ - KEYCACHE_DBUG_ASSERT(block); - /* Assert that block has a request and is not in LRU ring. */ - DBUG_ASSERT(block->requests); - DBUG_ASSERT(!block->next_used); - DBUG_ASSERT(!block->prev_used); - /* Assert that we return the correct block. */ - DBUG_ASSERT((page_status == PAGE_WAIT_TO_BE_READ) || - ((block->hash_link->file == file) && - (block->hash_link->diskpos == filepos))); - *page_st=page_status; - KEYCACHE_DBUG_PRINT("find_key_block", - ("fd: %d pos: %lu block->status: %u page_status: %d", - file, (ulong) filepos, block->status, - page_status)); - -#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) - DBUG_EXECUTE("check_keycache2", - test_key_cache(keycache, "end of find_key_block",0);); -#endif - KEYCACHE_THREAD_TRACE("find_key_block:end"); - DBUG_RETURN(block); -} - - -/* - Read into a key cache block buffer from disk. - - SYNOPSIS - - read_block() - keycache pointer to a key cache data structure - block block to which buffer the data is to be read - read_length size of data to be read - min_length at least so much data must be read - primary <-> the current thread will read the data - - RETURN VALUE - None - - NOTES. - The function either reads a page data from file to the block buffer, - or waits until another thread reads it. What page to read is determined - by a block parameter - reference to a hash link for this page. - If an error occurs THE BLOCK_ERROR bit is set in the block status. - We do not report error when the size of successfully read - portion is less than read_length, but not less than min_length. -*/ - -static void read_block(KEY_CACHE *keycache, - BLOCK_LINK *block, uint read_length, - uint min_length, my_bool primary) -{ - size_t got_length; - - /* On entry cache_lock is locked */ - - KEYCACHE_THREAD_TRACE("read_block"); - if (primary) - { - /* - This code is executed only by threads that submitted primary - requests. Until block->status contains BLOCK_READ, all other - request for the block become secondary requests. For a primary - request the block must be properly initialized. - */ - DBUG_ASSERT(((block->status & ~BLOCK_FOR_UPDATE) == BLOCK_IN_USE) || - fail_block(block)); - DBUG_ASSERT((block->length == 0) || fail_block(block)); - DBUG_ASSERT((block->offset == keycache->key_cache_block_size) || - fail_block(block)); - DBUG_ASSERT((block->requests > 0) || fail_block(block)); - - KEYCACHE_DBUG_PRINT("read_block", - ("page to be read by primary request")); - - keycache->global_cache_read++; - /* Page is not in buffer yet, is to be read from disk */ - keycache_pthread_mutex_unlock(&keycache->cache_lock); - /* - Here other threads may step in and register as secondary readers. - They will register in block->wqueue[COND_FOR_REQUESTED]. - */ - got_length= my_pread(block->hash_link->file, block->buffer, - read_length, block->hash_link->diskpos, MYF(0)); - keycache_pthread_mutex_lock(&keycache->cache_lock); - /* - The block can now have been marked for free (in case of - FLUSH_RELEASE). Otherwise the state must be unchanged. - */ - DBUG_ASSERT(((block->status & ~(BLOCK_REASSIGNED | - BLOCK_FOR_UPDATE)) == BLOCK_IN_USE) || - fail_block(block)); - DBUG_ASSERT((block->length == 0) || fail_block(block)); - DBUG_ASSERT((block->offset == keycache->key_cache_block_size) || - fail_block(block)); - DBUG_ASSERT((block->requests > 0) || fail_block(block)); - - if (got_length < min_length) - block->status|= BLOCK_ERROR; - else - { - block->status|= BLOCK_READ; - block->length= got_length; - /* - Do not set block->offset here. If this block is marked - BLOCK_CHANGED later, we want to flush only the modified part. So - only a writer may set block->offset down from - keycache->key_cache_block_size. - */ - } - KEYCACHE_DBUG_PRINT("read_block", - ("primary request: new page in cache")); - /* Signal that all pending requests for this page now can be processed */ - release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]); - } - else - { - /* - This code is executed only by threads that submitted secondary - requests. At this point it could happen that the cache block is - not yet assigned to the hash_link for the requested file block. - But at awake from the wait this should be the case. Unfortunately - we cannot assert this here because we do not know the hash_link - for the requested file block nor the file and position. So we have - to assert this in the caller. - */ - KEYCACHE_DBUG_PRINT("read_block", - ("secondary request waiting for new page to be read")); - wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock); - KEYCACHE_DBUG_PRINT("read_block", - ("secondary request: new page in cache")); - } -} - - -/* - Read a block of data from a cached file into a buffer; - - SYNOPSIS - - key_cache_read() - keycache pointer to a key cache data structure - file handler for the file for the block of data to be read - filepos position of the block of data in the file - level determines the weight of the data - buff buffer to where the data must be placed - length length of the buffer - block_length length of the block in the key cache buffer - return_buffer return pointer to the key cache buffer with the data - - RETURN VALUE - Returns address from where the data is placed if sucessful, 0 - otherwise. - - NOTES. - The function ensures that a block of data of size length from file - positioned at filepos is in the buffers for some key cache blocks. - Then the function either copies the data into the buffer buff, or, - if return_buffer is TRUE, it just returns the pointer to the key cache - buffer with the data. - Filepos must be a multiple of 'block_length', but it doesn't - have to be a multiple of key_cache_block_size; -*/ - -uchar *key_cache_read(KEY_CACHE *keycache, - File file, my_off_t filepos, int level, - uchar *buff, uint length, - uint block_length __attribute__((unused)), - int return_buffer __attribute__((unused))) -{ - my_bool locked_and_incremented= FALSE; - int error=0; - uchar *start= buff; - DBUG_ENTER("key_cache_read"); - DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u", - (uint) file, (ulong) filepos, length)); - - if (keycache->key_cache_inited) - { - /* Key cache is used */ - reg1 BLOCK_LINK *block; - uint read_length; - uint offset; - int page_st; - - if (MYSQL_KEYCACHE_READ_START_ENABLED()) - { - MYSQL_KEYCACHE_READ_START(my_filename(file), length, - (ulong) (keycache->blocks_used * - keycache->key_cache_block_size), - (ulong) (keycache->blocks_unused * - keycache->key_cache_block_size)); - } - - /* - When the key cache is once initialized, we use the cache_lock to - reliably distinguish the cases of normal operation, resizing, and - disabled cache. We always increment and decrement - 'cnt_for_resize_op' so that a resizer can wait for pending I/O. - */ - keycache_pthread_mutex_lock(&keycache->cache_lock); - /* - Cache resizing has two phases: Flushing and re-initializing. In - the flush phase read requests are allowed to bypass the cache for - blocks not in the cache. find_key_block() returns NULL in this - case. - - After the flush phase new I/O requests must wait until the - re-initialization is done. The re-initialization can be done only - if no I/O request is in progress. The reason is that - key_cache_block_size can change. With enabled cache, I/O is done - in chunks of key_cache_block_size. Every chunk tries to use a - cache block first. If the block size changes in the middle, a - block could be missed and old data could be read. - */ - while (keycache->in_resize && !keycache->resize_in_flush) - wait_on_queue(&keycache->resize_queue, &keycache->cache_lock); - /* Register the I/O for the next resize. */ - inc_counter_for_resize_op(keycache); - locked_and_incremented= TRUE; - /* Requested data may not always be aligned to cache blocks. */ - offset= (uint) (filepos % keycache->key_cache_block_size); - /* Read data in key_cache_block_size increments */ - do - { - /* Cache could be disabled in a later iteration. */ - if (!keycache->can_be_used) - { - KEYCACHE_DBUG_PRINT("key_cache_read", ("keycache cannot be used")); - goto no_key_cache; - } - /* Start reading at the beginning of the cache block. */ - filepos-= offset; - /* Do not read beyond the end of the cache block. */ - read_length= length; - set_if_smaller(read_length, keycache->key_cache_block_size-offset); - KEYCACHE_DBUG_ASSERT(read_length > 0); - - if (block_length > keycache->key_cache_block_size || offset) - return_buffer=0; - - /* Request the cache block that matches file/pos. */ - keycache->global_cache_r_requests++; - - MYSQL_KEYCACHE_READ_BLOCK(keycache->key_cache_block_size); - - block=find_key_block(keycache, file, filepos, level, 0, &page_st); - if (!block) - { - /* - This happens only for requests submitted during key cache - resize. The block is not in the cache and shall not go in. - Read directly from file. - */ - keycache->global_cache_read++; - keycache_pthread_mutex_unlock(&keycache->cache_lock); - error= (my_pread(file, (uchar*) buff, read_length, - filepos + offset, MYF(MY_NABP)) != 0); - keycache_pthread_mutex_lock(&keycache->cache_lock); - goto next_block; - } - if (!(block->status & BLOCK_ERROR)) - { - if (page_st != PAGE_READ) - { - MYSQL_KEYCACHE_READ_MISS(); - /* The requested page is to be read into the block buffer */ - read_block(keycache, block, - keycache->key_cache_block_size, read_length+offset, - (my_bool)(page_st == PAGE_TO_BE_READ)); - /* - A secondary request must now have the block assigned to the - requested file block. It does not hurt to check it for - primary requests too. - */ - DBUG_ASSERT(keycache->can_be_used); - DBUG_ASSERT(block->hash_link->file == file); - DBUG_ASSERT(block->hash_link->diskpos == filepos); - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - } - else if (block->length < read_length + offset) - { - /* - Impossible if nothing goes wrong: - this could only happen if we are using a file with - small key blocks and are trying to read outside the file - */ - my_errno= -1; - block->status|= BLOCK_ERROR; - } - else - { - MYSQL_KEYCACHE_READ_HIT(); - } - } - - /* block status may have added BLOCK_ERROR in the above 'if'. */ - if (!(block->status & BLOCK_ERROR)) - { - { - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); -#if !defined(SERIALIZED_READ_FROM_CACHE) - keycache_pthread_mutex_unlock(&keycache->cache_lock); -#endif - - /* Copy data from the cache buffer */ - memcpy(buff, block->buffer+offset, (size_t) read_length); - -#if !defined(SERIALIZED_READ_FROM_CACHE) - keycache_pthread_mutex_lock(&keycache->cache_lock); - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); -#endif - } - } - - remove_reader(block); - - /* Error injection for coverage testing. */ - DBUG_EXECUTE_IF("key_cache_read_block_error", - block->status|= BLOCK_ERROR;); - - /* Do not link erroneous blocks into the LRU ring, but free them. */ - if (!(block->status & BLOCK_ERROR)) - { - /* - Link the block into the LRU ring if it's the last submitted - request for the block. This enables eviction for the block. - */ - unreg_request(keycache, block, 1); - } - else - { - free_block(keycache, block); - error= 1; - break; - } - - next_block: - buff+= read_length; - filepos+= read_length+offset; - offset= 0; - - } while ((length-= read_length)); - if (MYSQL_KEYCACHE_READ_DONE_ENABLED()) - { - MYSQL_KEYCACHE_READ_DONE((ulong) (keycache->blocks_used * - keycache->key_cache_block_size), - (ulong) (keycache->blocks_unused * - keycache->key_cache_block_size)); - } - goto end; - } - KEYCACHE_DBUG_PRINT("key_cache_read", ("keycache not initialized")); - -no_key_cache: - /* Key cache is not used */ - - keycache->global_cache_r_requests++; - keycache->global_cache_read++; - - if (locked_and_incremented) - keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (my_pread(file, (uchar*) buff, length, filepos, MYF(MY_NABP))) - error= 1; - if (locked_and_incremented) - keycache_pthread_mutex_lock(&keycache->cache_lock); - -end: - if (locked_and_incremented) - { - dec_counter_for_resize_op(keycache); - keycache_pthread_mutex_unlock(&keycache->cache_lock); - } - DBUG_PRINT("exit", ("error: %d", error )); - DBUG_RETURN(error ? (uchar*) 0 : start); -} - - -/* - Insert a block of file data from a buffer into key cache - - SYNOPSIS - key_cache_insert() - keycache pointer to a key cache data structure - file handler for the file to insert data from - filepos position of the block of data in the file to insert - level determines the weight of the data - buff buffer to read data from - length length of the data in the buffer - - NOTES - This is used by MyISAM to move all blocks from a index file to the key - cache - - RETURN VALUE - 0 if a success, 1 - otherwise. -*/ - -int key_cache_insert(KEY_CACHE *keycache, - File file, my_off_t filepos, int level, - uchar *buff, uint length) -{ - int error= 0; - DBUG_ENTER("key_cache_insert"); - DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u", - (uint) file,(ulong) filepos, length)); - - if (keycache->key_cache_inited) - { - /* Key cache is used */ - reg1 BLOCK_LINK *block; - uint read_length; - uint offset; - int page_st; - my_bool locked_and_incremented= FALSE; - - /* - When the keycache is once initialized, we use the cache_lock to - reliably distinguish the cases of normal operation, resizing, and - disabled cache. We always increment and decrement - 'cnt_for_resize_op' so that a resizer can wait for pending I/O. - */ - keycache_pthread_mutex_lock(&keycache->cache_lock); - /* - We do not load index data into a disabled cache nor into an - ongoing resize. - */ - if (!keycache->can_be_used || keycache->in_resize) - goto no_key_cache; - /* Register the pseudo I/O for the next resize. */ - inc_counter_for_resize_op(keycache); - locked_and_incremented= TRUE; - /* Loaded data may not always be aligned to cache blocks. */ - offset= (uint) (filepos % keycache->key_cache_block_size); - /* Load data in key_cache_block_size increments. */ - do - { - /* Cache could be disabled or resizing in a later iteration. */ - if (!keycache->can_be_used || keycache->in_resize) - goto no_key_cache; - /* Start loading at the beginning of the cache block. */ - filepos-= offset; - /* Do not load beyond the end of the cache block. */ - read_length= length; - set_if_smaller(read_length, keycache->key_cache_block_size-offset); - KEYCACHE_DBUG_ASSERT(read_length > 0); - - /* The block has been read by the caller already. */ - keycache->global_cache_read++; - /* Request the cache block that matches file/pos. */ - keycache->global_cache_r_requests++; - block= find_key_block(keycache, file, filepos, level, 0, &page_st); - if (!block) - { - /* - This happens only for requests submitted during key cache - resize. The block is not in the cache and shall not go in. - Stop loading index data. - */ - goto no_key_cache; - } - if (!(block->status & BLOCK_ERROR)) - { - if ((page_st == PAGE_WAIT_TO_BE_READ) || - ((page_st == PAGE_TO_BE_READ) && - (offset || (read_length < keycache->key_cache_block_size)))) - { - /* - Either - - this is a secondary request for a block to be read into the - cache. The block is in eviction. It is not yet assigned to - the requested file block (It does not point to the right - hash_link). So we cannot call remove_reader() on the block. - And we cannot access the hash_link directly here. We need to - wait until the assignment is complete. read_block() executes - the correct wait when called with primary == FALSE. - - Or - - this is a primary request for a block to be read into the - cache and the supplied data does not fill the whole block. - - This function is called on behalf of a LOAD INDEX INTO CACHE - statement, which is a read-only task and allows other - readers. It is possible that a parallel running reader tries - to access this block. If it needs more data than has been - supplied here, it would report an error. To be sure that we - have all data in the block that is available in the file, we - read the block ourselves. - - Though reading again what the caller did read already is an - expensive operation, we need to do this for correctness. - */ - read_block(keycache, block, keycache->key_cache_block_size, - read_length + offset, (page_st == PAGE_TO_BE_READ)); - /* - A secondary request must now have the block assigned to the - requested file block. It does not hurt to check it for - primary requests too. - */ - DBUG_ASSERT(keycache->can_be_used); - DBUG_ASSERT(block->hash_link->file == file); - DBUG_ASSERT(block->hash_link->diskpos == filepos); - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - } - else if (page_st == PAGE_TO_BE_READ) - { - /* - This is a new block in the cache. If we come here, we have - data for the whole block. - */ - DBUG_ASSERT(block->hash_link->requests); - DBUG_ASSERT(block->status & BLOCK_IN_USE); - DBUG_ASSERT((page_st == PAGE_TO_BE_READ) || - (block->status & BLOCK_READ)); - -#if !defined(SERIALIZED_READ_FROM_CACHE) - keycache_pthread_mutex_unlock(&keycache->cache_lock); - /* - Here other threads may step in and register as secondary readers. - They will register in block->wqueue[COND_FOR_REQUESTED]. - */ -#endif - - /* Copy data from buff */ - memcpy(block->buffer+offset, buff, (size_t) read_length); - -#if !defined(SERIALIZED_READ_FROM_CACHE) - keycache_pthread_mutex_lock(&keycache->cache_lock); - DBUG_ASSERT(block->status & BLOCK_IN_USE); - DBUG_ASSERT((page_st == PAGE_TO_BE_READ) || - (block->status & BLOCK_READ)); -#endif - /* - After the data is in the buffer, we can declare the block - valid. Now other threads do not need to register as - secondary readers any more. They can immediately access the - block. - */ - block->status|= BLOCK_READ; - block->length= read_length+offset; - /* - Do not set block->offset here. If this block is marked - BLOCK_CHANGED later, we want to flush only the modified part. So - only a writer may set block->offset down from - keycache->key_cache_block_size. - */ - KEYCACHE_DBUG_PRINT("key_cache_insert", - ("primary request: new page in cache")); - /* Signal all pending requests. */ - release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]); - } - else - { - /* - page_st == PAGE_READ. The block is in the buffer. All data - must already be present. Blocks are always read with all - data available on file. Assert that the block does not have - less contents than the preloader supplies. If the caller has - data beyond block->length, it means that a file write has - been done while this block was in cache and not extended - with the new data. If the condition is met, we can simply - ignore the block. - */ - DBUG_ASSERT((page_st == PAGE_READ) && - (read_length + offset <= block->length)); - } - - /* - A secondary request must now have the block assigned to the - requested file block. It does not hurt to check it for primary - requests too. - */ - DBUG_ASSERT(block->hash_link->file == file); - DBUG_ASSERT(block->hash_link->diskpos == filepos); - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - } /* end of if (!(block->status & BLOCK_ERROR)) */ - - remove_reader(block); - - /* Error injection for coverage testing. */ - DBUG_EXECUTE_IF("key_cache_insert_block_error", - block->status|= BLOCK_ERROR; errno=EIO;); - - /* Do not link erroneous blocks into the LRU ring, but free them. */ - if (!(block->status & BLOCK_ERROR)) - { - /* - Link the block into the LRU ring if it's the last submitted - request for the block. This enables eviction for the block. - */ - unreg_request(keycache, block, 1); - } - else - { - free_block(keycache, block); - error= 1; - break; - } - - buff+= read_length; - filepos+= read_length+offset; - offset= 0; - - } while ((length-= read_length)); - - no_key_cache: - if (locked_and_incremented) - dec_counter_for_resize_op(keycache); - keycache_pthread_mutex_unlock(&keycache->cache_lock); - } - DBUG_RETURN(error); -} - - -/* - Write a buffer into a cached file. - - SYNOPSIS - - key_cache_write() - keycache pointer to a key cache data structure - file handler for the file to write data to - filepos position in the file to write data to - level determines the weight of the data - buff buffer with the data - length length of the buffer - dont_write if is 0 then all dirty pages involved in writing - should have been flushed from key cache - - RETURN VALUE - 0 if a success, 1 - otherwise. - - NOTES. - The function copies the data of size length from buff into buffers - for key cache blocks that are assigned to contain the portion of - the file starting with position filepos. - It ensures that this data is flushed to the file if dont_write is FALSE. - Filepos must be a multiple of 'block_length', but it doesn't - have to be a multiple of key_cache_block_size; - - dont_write is always TRUE in the server (info->lock_type is never F_UNLCK). -*/ - -int key_cache_write(KEY_CACHE *keycache, - File file, my_off_t filepos, int level, - uchar *buff, uint length, - uint block_length __attribute__((unused)), - int dont_write) -{ - my_bool locked_and_incremented= FALSE; - int error=0; - DBUG_ENTER("key_cache_write"); - DBUG_PRINT("enter", - ("fd: %u pos: %lu length: %u block_length: %u" - " key_block_length: %u", - (uint) file, (ulong) filepos, length, block_length, - keycache ? keycache->key_cache_block_size : 0)); - - if (!dont_write) - { - /* purecov: begin inspected */ - /* Not used in the server. */ - /* Force writing from buff into disk. */ - keycache->global_cache_w_requests++; - keycache->global_cache_write++; - if (my_pwrite(file, buff, length, filepos, MYF(MY_NABP | MY_WAIT_IF_FULL))) - DBUG_RETURN(1); - /* purecov: end */ - } - -#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) - DBUG_EXECUTE("check_keycache", - test_key_cache(keycache, "start of key_cache_write", 1);); -#endif - - if (keycache->key_cache_inited) - { - /* Key cache is used */ - reg1 BLOCK_LINK *block; - uint read_length; - uint offset; - int page_st; - - if (MYSQL_KEYCACHE_WRITE_START_ENABLED()) - { - MYSQL_KEYCACHE_WRITE_START(my_filename(file), length, - (ulong) (keycache->blocks_used * - keycache->key_cache_block_size), - (ulong) (keycache->blocks_unused * - keycache->key_cache_block_size)); - } - - /* - When the key cache is once initialized, we use the cache_lock to - reliably distinguish the cases of normal operation, resizing, and - disabled cache. We always increment and decrement - 'cnt_for_resize_op' so that a resizer can wait for pending I/O. - */ - keycache_pthread_mutex_lock(&keycache->cache_lock); - /* - Cache resizing has two phases: Flushing and re-initializing. In - the flush phase write requests can modify dirty blocks that are - not yet in flush. Otherwise they are allowed to bypass the cache. - find_key_block() returns NULL in both cases (clean blocks and - non-cached blocks). - - After the flush phase new I/O requests must wait until the - re-initialization is done. The re-initialization can be done only - if no I/O request is in progress. The reason is that - key_cache_block_size can change. With enabled cache I/O is done in - chunks of key_cache_block_size. Every chunk tries to use a cache - block first. If the block size changes in the middle, a block - could be missed and data could be written below a cached block. - */ - while (keycache->in_resize && !keycache->resize_in_flush) - wait_on_queue(&keycache->resize_queue, &keycache->cache_lock); - /* Register the I/O for the next resize. */ - inc_counter_for_resize_op(keycache); - locked_and_incremented= TRUE; - /* Requested data may not always be aligned to cache blocks. */ - offset= (uint) (filepos % keycache->key_cache_block_size); - /* Write data in key_cache_block_size increments. */ - do - { - /* Cache could be disabled in a later iteration. */ - if (!keycache->can_be_used) - goto no_key_cache; - - MYSQL_KEYCACHE_WRITE_BLOCK(keycache->key_cache_block_size); - /* Start writing at the beginning of the cache block. */ - filepos-= offset; - /* Do not write beyond the end of the cache block. */ - read_length= length; - set_if_smaller(read_length, keycache->key_cache_block_size-offset); - KEYCACHE_DBUG_ASSERT(read_length > 0); - - /* Request the cache block that matches file/pos. */ - keycache->global_cache_w_requests++; - block= find_key_block(keycache, file, filepos, level, 1, &page_st); - if (!block) - { - /* - This happens only for requests submitted during key cache - resize. The block is not in the cache and shall not go in. - Write directly to file. - */ - if (dont_write) - { - /* Used in the server. */ - keycache->global_cache_write++; - keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (my_pwrite(file, (uchar*) buff, read_length, filepos + offset, - MYF(MY_NABP | MY_WAIT_IF_FULL))) - error=1; - keycache_pthread_mutex_lock(&keycache->cache_lock); - } - goto next_block; - } - /* - Prevent block from flushing and from being selected for to be - freed. This must be set when we release the cache_lock. - However, we must not set the status of the block before it is - assigned to this file/pos. - */ - if (page_st != PAGE_WAIT_TO_BE_READ) - block->status|= BLOCK_FOR_UPDATE; - /* - We must read the file block first if it is not yet in the cache - and we do not replace all of its contents. - - In cases where the cache block is big enough to contain (parts - of) index blocks of different indexes, our request can be - secondary (PAGE_WAIT_TO_BE_READ). In this case another thread is - reading the file block. If the read completes after us, it - overwrites our new contents with the old contents. So we have to - wait for the other thread to complete the read of this block. - read_block() takes care for the wait. - */ - if (!(block->status & BLOCK_ERROR) && - ((page_st == PAGE_TO_BE_READ && - (offset || read_length < keycache->key_cache_block_size)) || - (page_st == PAGE_WAIT_TO_BE_READ))) - { - read_block(keycache, block, - offset + read_length >= keycache->key_cache_block_size? - offset : keycache->key_cache_block_size, - offset, (page_st == PAGE_TO_BE_READ)); - DBUG_ASSERT(keycache->can_be_used); - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - /* - Prevent block from flushing and from being selected for to be - freed. This must be set when we release the cache_lock. - Here we set it in case we could not set it above. - */ - block->status|= BLOCK_FOR_UPDATE; - } - /* - The block should always be assigned to the requested file block - here. It need not be BLOCK_READ when overwriting the whole block. - */ - DBUG_ASSERT(block->hash_link->file == file); - DBUG_ASSERT(block->hash_link->diskpos == filepos); - DBUG_ASSERT(block->status & BLOCK_IN_USE); - DBUG_ASSERT((page_st == PAGE_TO_BE_READ) || (block->status & BLOCK_READ)); - /* - The block to be written must not be marked BLOCK_REASSIGNED. - Otherwise it could be freed in dirty state or reused without - another flush during eviction. It must also not be in flush. - Otherwise the old contens may have been flushed already and - the flusher could clear BLOCK_CHANGED without flushing the - new changes again. - */ - DBUG_ASSERT(!(block->status & BLOCK_REASSIGNED)); - - while (block->status & BLOCK_IN_FLUSHWRITE) - { - /* - Another thread is flushing the block. It was dirty already. - Wait until the block is flushed to file. Otherwise we could - modify the buffer contents just while it is written to file. - An unpredictable file block contents would be the result. - While we wait, several things can happen to the block, - including another flush. But the block cannot be reassigned to - another hash_link until we release our request on it. - */ - wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock); - DBUG_ASSERT(keycache->can_be_used); - DBUG_ASSERT(block->status & (BLOCK_READ | BLOCK_IN_USE)); - /* Still must not be marked for free. */ - DBUG_ASSERT(!(block->status & BLOCK_REASSIGNED)); - DBUG_ASSERT(block->hash_link && (block->hash_link->block == block)); - } - - /* - We could perhaps release the cache_lock during access of the - data like in the other functions. Locks outside of the key cache - assure that readers and a writer do not access the same range of - data. Parallel accesses should happen only if the cache block - contains multiple index block(fragment)s. So different parts of - the buffer would be read/written. An attempt to flush during - memcpy() is prevented with BLOCK_FOR_UPDATE. - */ - if (!(block->status & BLOCK_ERROR)) - { -#if !defined(SERIALIZED_READ_FROM_CACHE) - keycache_pthread_mutex_unlock(&keycache->cache_lock); -#endif - memcpy(block->buffer+offset, buff, (size_t) read_length); - -#if !defined(SERIALIZED_READ_FROM_CACHE) - keycache_pthread_mutex_lock(&keycache->cache_lock); -#endif - } - - if (!dont_write) - { - /* Not used in the server. buff has been written to disk at start. */ - if ((block->status & BLOCK_CHANGED) && - (!offset && read_length >= keycache->key_cache_block_size)) - link_to_file_list(keycache, block, block->hash_link->file, 1); - } - else if (! (block->status & BLOCK_CHANGED)) - link_to_changed_list(keycache, block); - block->status|=BLOCK_READ; - /* - Allow block to be selected for to be freed. Since it is marked - BLOCK_CHANGED too, it won't be selected for to be freed without - a flush. - */ - block->status&= ~BLOCK_FOR_UPDATE; - set_if_smaller(block->offset, offset); - set_if_bigger(block->length, read_length+offset); - - /* Threads may be waiting for the changes to be complete. */ - release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]); - - /* - If only a part of the cache block is to be replaced, and the - rest has been read from file, then the cache lock has been - released for I/O and it could be possible that another thread - wants to evict or free the block and waits for it to be - released. So we must not just decrement hash_link->requests, but - also wake a waiting thread. - */ - remove_reader(block); - - /* Error injection for coverage testing. */ - DBUG_EXECUTE_IF("key_cache_write_block_error", - block->status|= BLOCK_ERROR;); - - /* Do not link erroneous blocks into the LRU ring, but free them. */ - if (!(block->status & BLOCK_ERROR)) - { - /* - Link the block into the LRU ring if it's the last submitted - request for the block. This enables eviction for the block. - */ - unreg_request(keycache, block, 1); - } - else - { - /* Pretend a "clean" block to avoid complications. */ - block->status&= ~(BLOCK_CHANGED); - free_block(keycache, block); - error= 1; - break; - } - - next_block: - buff+= read_length; - filepos+= read_length+offset; - offset= 0; - - } while ((length-= read_length)); - goto end; - } - -no_key_cache: - /* Key cache is not used */ - if (dont_write) - { - /* Used in the server. */ - keycache->global_cache_w_requests++; - keycache->global_cache_write++; - if (locked_and_incremented) - keycache_pthread_mutex_unlock(&keycache->cache_lock); - if (my_pwrite(file, (uchar*) buff, length, filepos, - MYF(MY_NABP | MY_WAIT_IF_FULL))) - error=1; - if (locked_and_incremented) - keycache_pthread_mutex_lock(&keycache->cache_lock); - } - -end: - if (locked_and_incremented) - { - dec_counter_for_resize_op(keycache); - keycache_pthread_mutex_unlock(&keycache->cache_lock); - } - - if (MYSQL_KEYCACHE_WRITE_DONE_ENABLED()) - { - MYSQL_KEYCACHE_WRITE_DONE((ulong) (keycache->blocks_used * - keycache->key_cache_block_size), - (ulong) (keycache->blocks_unused * - keycache->key_cache_block_size)); - } - -#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) - DBUG_EXECUTE("exec", - test_key_cache(keycache, "end of key_cache_write", 1);); -#endif - DBUG_RETURN(error); -} - - -/* - Free block. - - SYNOPSIS - free_block() - keycache Pointer to a key cache data structure - block Pointer to the block to free - - DESCRIPTION - Remove reference to block from hash table. - Remove block from the chain of clean blocks. - Add block to the free list. - - NOTE - Block must not be free (status == 0). - Block must not be in free_block_list. - Block must not be in the LRU ring. - Block must not be in eviction (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH). - Block must not be in free (BLOCK_REASSIGNED). - Block must not be in flush (BLOCK_IN_FLUSH). - Block must not be dirty (BLOCK_CHANGED). - Block must not be in changed_blocks (dirty) hash. - Block must be in file_blocks (clean) hash. - Block must refer to a hash_link. - Block must have a request registered on it. -*/ - -static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block) -{ - KEYCACHE_THREAD_TRACE("free block"); - KEYCACHE_DBUG_PRINT("free_block", - ("block %u to be freed, hash_link %p status: %u", - BLOCK_NUMBER(block), block->hash_link, - block->status)); - /* - Assert that the block is not free already. And that it is in a clean - state. Note that the block might just be assigned to a hash_link and - not yet read (BLOCK_READ may not be set here). In this case a reader - is registered in the hash_link and free_block() will wait for it - below. - */ - DBUG_ASSERT((block->status & BLOCK_IN_USE) && - !(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | - BLOCK_REASSIGNED | BLOCK_IN_FLUSH | - BLOCK_CHANGED | BLOCK_FOR_UPDATE))); - /* Assert that the block is in a file_blocks chain. */ - DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); - /* Assert that the block is not in the LRU ring. */ - DBUG_ASSERT(!block->next_used && !block->prev_used); - /* - IMHO the below condition (if()) makes no sense. I can't see how it - could be possible that free_block() is entered with a NULL hash_link - pointer. The only place where it can become NULL is in free_block() - (or before its first use ever, but for those blocks free_block() is - not called). I don't remove the conditional as it cannot harm, but - place an DBUG_ASSERT to confirm my hypothesis. Eventually the - condition (if()) can be removed. - */ - DBUG_ASSERT(block->hash_link && block->hash_link->block == block); - if (block->hash_link) - { - /* - While waiting for readers to finish, new readers might request the - block. But since we set block->status|= BLOCK_REASSIGNED, they - will wait on block->wqueue[COND_FOR_SAVED]. They must be signalled - later. - */ - block->status|= BLOCK_REASSIGNED; - wait_for_readers(keycache, block); - /* - The block must not have been freed by another thread. Repeat some - checks. An additional requirement is that it must be read now - (BLOCK_READ). - */ - DBUG_ASSERT(block->hash_link && block->hash_link->block == block); - DBUG_ASSERT((block->status & (BLOCK_READ | BLOCK_IN_USE | - BLOCK_REASSIGNED)) && - !(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | - BLOCK_IN_FLUSH | BLOCK_CHANGED | - BLOCK_FOR_UPDATE))); - DBUG_ASSERT(block->prev_changed && *block->prev_changed == block); - DBUG_ASSERT(!block->prev_used); - /* - Unset BLOCK_REASSIGNED again. If we hand the block to an evicting - thread (through unreg_request() below), other threads must not see - this flag. They could become confused. - */ - block->status&= ~BLOCK_REASSIGNED; - /* - Do not release the hash_link until the block is off all lists. - At least not if we hand it over for eviction in unreg_request(). - */ - } - - /* - Unregister the block request and link the block into the LRU ring. - This enables eviction for the block. If the LRU ring was empty and - threads are waiting for a block, then the block wil be handed over - for eviction immediately. Otherwise we will unlink it from the LRU - ring again, without releasing the lock in between. So decrementing - the request counter and updating statistics are the only relevant - operation in this case. Assert that there are no other requests - registered. - */ - DBUG_ASSERT(block->requests == 1); - unreg_request(keycache, block, 0); - /* - Note that even without releasing the cache lock it is possible that - the block is immediately selected for eviction by link_block() and - thus not added to the LRU ring. In this case we must not touch the - block any more. - */ - if (block->status & BLOCK_IN_EVICTION) - return; - - /* Error blocks are not put into the LRU ring. */ - if (!(block->status & BLOCK_ERROR)) - { - /* Here the block must be in the LRU ring. Unlink it again. */ - DBUG_ASSERT(block->next_used && block->prev_used && - *block->prev_used == block); - unlink_block(keycache, block); - } - if (block->temperature == BLOCK_WARM) - keycache->warm_blocks--; - block->temperature= BLOCK_COLD; - - /* Remove from file_blocks hash. */ - unlink_changed(block); - - /* Remove reference to block from hash table. */ - unlink_hash(keycache, block->hash_link); - block->hash_link= NULL; - - block->status= 0; - block->length= 0; - block->offset= keycache->key_cache_block_size; - KEYCACHE_THREAD_TRACE("free block"); - KEYCACHE_DBUG_PRINT("free_block", ("block is freed")); - - /* Enforced by unlink_changed(), but just to be sure. */ - DBUG_ASSERT(!block->next_changed && !block->prev_changed); - /* Enforced by unlink_block(): not in LRU ring nor in free_block_list. */ - DBUG_ASSERT(!block->next_used && !block->prev_used); - /* Insert the free block in the free list. */ - block->next_used= keycache->free_block_list; - keycache->free_block_list= block; - /* Keep track of the number of currently unused blocks. */ - keycache->blocks_unused++; - - /* All pending requests for this page must be resubmitted. */ - release_whole_queue(&block->wqueue[COND_FOR_SAVED]); -} - - -static int cmp_sec_link(BLOCK_LINK **a, BLOCK_LINK **b) -{ - return (((*a)->hash_link->diskpos < (*b)->hash_link->diskpos) ? -1 : - ((*a)->hash_link->diskpos > (*b)->hash_link->diskpos) ? 1 : 0); -} - - -/* - Flush a portion of changed blocks to disk, - free used blocks if requested -*/ - -static int flush_cached_blocks(KEY_CACHE *keycache, - File file, BLOCK_LINK **cache, - BLOCK_LINK **end, - enum flush_type type) -{ - int error; - int last_errno= 0; - uint count= (uint) (end-cache); - - /* Don't lock the cache during the flush */ - keycache_pthread_mutex_unlock(&keycache->cache_lock); - /* - As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH - we are guarunteed no thread will change them - */ - my_qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link); - - keycache_pthread_mutex_lock(&keycache->cache_lock); - /* - Note: Do not break the loop. We have registered a request on every - block in 'cache'. These must be unregistered by free_block() or - unreg_request(). - */ - for ( ; cache != end ; cache++) - { - BLOCK_LINK *block= *cache; - - KEYCACHE_DBUG_PRINT("flush_cached_blocks", - ("block %u to be flushed", BLOCK_NUMBER(block))); - /* - If the block contents is going to be changed, we abandon the flush - for this block. flush_key_blocks_int() will restart its search and - handle the block properly. - */ - if (!(block->status & BLOCK_FOR_UPDATE)) - { - /* Blocks coming here must have a certain status. */ - DBUG_ASSERT(block->hash_link); - DBUG_ASSERT(block->hash_link->block == block); - DBUG_ASSERT(block->hash_link->file == file); - DBUG_ASSERT((block->status & ~BLOCK_IN_EVICTION) == - (BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE)); - block->status|= BLOCK_IN_FLUSHWRITE; - keycache_pthread_mutex_unlock(&keycache->cache_lock); - error= my_pwrite(file, block->buffer+block->offset, - block->length - block->offset, - block->hash_link->diskpos+ block->offset, - MYF(MY_NABP | MY_WAIT_IF_FULL)); - keycache_pthread_mutex_lock(&keycache->cache_lock); - keycache->global_cache_write++; - if (error) - { - block->status|= BLOCK_ERROR; - if (!last_errno) - last_errno= errno ? errno : -1; - } - block->status&= ~BLOCK_IN_FLUSHWRITE; - /* Block must not have changed status except BLOCK_FOR_UPDATE. */ - DBUG_ASSERT(block->hash_link); - DBUG_ASSERT(block->hash_link->block == block); - DBUG_ASSERT(block->hash_link->file == file); - DBUG_ASSERT((block->status & ~(BLOCK_FOR_UPDATE | BLOCK_IN_EVICTION)) == - (BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE)); - /* - Set correct status and link in right queue for free or later use. - free_block() must not see BLOCK_CHANGED and it may need to wait - for readers of the block. These should not see the block in the - wrong hash. If not freeing the block, we need to have it in the - right queue anyway. - */ - link_to_file_list(keycache, block, file, 1); - } - block->status&= ~BLOCK_IN_FLUSH; - /* - 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. - */ - release_whole_queue(&block->wqueue[COND_FOR_SAVED]); - /* type will never be FLUSH_IGNORE_CHANGED here */ - if (!(type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE) && - !(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | - BLOCK_FOR_UPDATE))) - { - /* - Note that a request has been registered against the block in - flush_key_blocks_int(). - */ - free_block(keycache, block); - } - else - { - /* - Link the block into the LRU ring if it's the last submitted - request for the block. This enables eviction for the block. - Note that a request has been registered against the block in - flush_key_blocks_int(). - */ - unreg_request(keycache, block, 1); - } - - } /* end of for ( ; cache != end ; cache++) */ - return last_errno; -} - - -/* - Flush all key blocks for a file to disk, but don't do any mutex locks. - - SYNOPSIS - flush_key_blocks_int() - keycache pointer to a key cache data structure - file handler for the file to flush to - flush_type type of the flush - - NOTES - This function doesn't do any mutex locks because it needs to be called both - from flush_key_blocks and flush_all_key_blocks (the later one does the - mutex lock in the resize_key_cache() function). - - We do only care about changed blocks that exist when the function is - entered. We do not guarantee that all changed blocks of the file are - flushed if more blocks change while this function is running. - - RETURN - 0 ok - 1 error -*/ - -static int flush_key_blocks_int(KEY_CACHE *keycache, - File file, enum flush_type type) -{ - BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache; - int last_errno= 0; - int last_errcnt= 0; - DBUG_ENTER("flush_key_blocks_int"); - DBUG_PRINT("enter",("file: %d blocks_used: %lu blocks_changed: %lu", - file, keycache->blocks_used, keycache->blocks_changed)); - -#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG) - DBUG_EXECUTE("check_keycache", - test_key_cache(keycache, "start of flush_key_blocks", 0);); -#endif - - cache= cache_buff; - if (keycache->disk_blocks > 0 && - (!my_disable_flush_key_blocks || type != FLUSH_KEEP)) - { - /* Key cache exists and flush is not disabled */ - int error= 0; - uint count= FLUSH_CACHE; - BLOCK_LINK **pos,**end; - BLOCK_LINK *first_in_switch= NULL; - BLOCK_LINK *last_in_flush; - BLOCK_LINK *last_for_update; - BLOCK_LINK *block, *next; -#if defined(KEYCACHE_DEBUG) - uint cnt=0; -#endif - - if (type != FLUSH_IGNORE_CHANGED) - { - /* - Count how many key blocks we have to cache to be able - to flush all dirty pages with minimum seek moves - */ - count= 0; - for (block= keycache->changed_blocks[FILE_HASH(file)] ; - block ; - block= block->next_changed) - { - if ((block->hash_link->file == file) && - !(block->status & BLOCK_IN_FLUSH)) - { - count++; - KEYCACHE_DBUG_ASSERT(count<= keycache->blocks_used); - } - } - /* - Allocate a new buffer only if its bigger than the one we have. - Assure that we always have some entries for the case that new - changed blocks appear while we need to wait for something. - */ - if ((count > FLUSH_CACHE) && - !(cache= (BLOCK_LINK**) my_malloc(sizeof(BLOCK_LINK*)*count, - MYF(0)))) - cache= cache_buff; - /* - After a restart there could be more changed blocks than now. - So we should not let count become smaller than the fixed buffer. - */ - if (cache == cache_buff) - count= FLUSH_CACHE; - } - - /* Retrieve the blocks and write them to a buffer to be flushed */ -restart: - last_in_flush= NULL; - last_for_update= NULL; - end= (pos= cache)+count; - for (block= keycache->changed_blocks[FILE_HASH(file)] ; - block ; - block= next) - { -#if defined(KEYCACHE_DEBUG) - cnt++; - KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used); -#endif - next= block->next_changed; - if (block->hash_link->file == file) - { - if (!(block->status & (BLOCK_IN_FLUSH | BLOCK_FOR_UPDATE))) - { - /* - Note: The special handling of BLOCK_IN_SWITCH is obsolete - since we set BLOCK_IN_FLUSH if the eviction includes a - flush. It can be removed in a later version. - */ - if (!(block->status & BLOCK_IN_SWITCH)) - { - /* - We care only for the blocks for which flushing was not - initiated by another thread and which are not in eviction. - Registering a request on the block unlinks it from the LRU - ring and protects against eviction. - */ - reg_requests(keycache, block, 1); - if (type != FLUSH_IGNORE_CHANGED) - { - /* It's not a temporary file */ - if (pos == end) - { - /* - This should happen relatively seldom. Remove the - request because we won't do anything with the block - but restart and pick it again in the next iteration. - */ - unreg_request(keycache, block, 0); - /* - This happens only if there is not enough - memory for the big block - */ - if ((error= flush_cached_blocks(keycache, file, cache, - end,type))) - { - /* Do not loop infinitely trying to flush in vain. */ - if ((last_errno == error) && (++last_errcnt > 5)) - goto err; - last_errno= error; - } - /* - Restart the scan as some other thread might have changed - the changed blocks chain: the blocks that were in switch - state before the flush started have to be excluded - */ - goto restart; - } - /* - Mark the block with BLOCK_IN_FLUSH in order not to let - other threads to use it for new pages and interfere with - our sequence of flushing dirty file pages. We must not - set this flag before actually putting the block on the - write burst array called 'cache'. - */ - block->status|= BLOCK_IN_FLUSH; - /* Add block to the array for a write burst. */ - *pos++= block; - } - else - { - /* It's a temporary file */ - DBUG_ASSERT(!(block->status & BLOCK_REASSIGNED)); - /* - free_block() must not be called with BLOCK_CHANGED. Note - that we must not change the BLOCK_CHANGED flag outside of - link_to_file_list() so that it is always in the correct - queue and the *blocks_changed counters are correct. - */ - link_to_file_list(keycache, block, file, 1); - if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))) - { - /* A request has been registered against the block above. */ - free_block(keycache, block); - } - else - { - /* - Link the block into the LRU ring if it's the last - submitted request for the block. This enables eviction - for the block. A request has been registered against - the block above. - */ - unreg_request(keycache, block, 1); - } - } - } - else - { - /* - Link the block into a list of blocks 'in switch'. - - WARNING: Here we introduce a place where a changed block - is not in the changed_blocks hash! This is acceptable for - a BLOCK_IN_SWITCH. Never try this for another situation. - Other parts of the key cache code rely on changed blocks - being in the changed_blocks hash. - */ - unlink_changed(block); - link_changed(block, &first_in_switch); - } - } - else if (type != FLUSH_KEEP) - { - /* - During the normal flush at end of statement (FLUSH_KEEP) we - do not need to ensure that blocks in flush or update by - other threads are flushed. They will be flushed by them - later. In all other cases we must assure that we do not have - any changed block of this file in the cache when this - function returns. - */ - if (block->status & BLOCK_IN_FLUSH) - { - /* Remember the last block found to be in flush. */ - last_in_flush= block; - } - else - { - /* Remember the last block found to be selected for update. */ - last_for_update= block; - } - } - } - } - if (pos != cache) - { - if ((error= flush_cached_blocks(keycache, file, cache, pos, type))) - { - /* Do not loop inifnitely trying to flush in vain. */ - if ((last_errno == error) && (++last_errcnt > 5)) - goto err; - last_errno= error; - } - /* - Do not restart here during the normal flush at end of statement - (FLUSH_KEEP). We have now flushed at least all blocks that were - changed when entering this function. In all other cases we must - assure that we do not have any changed block of this file in the - cache when this function returns. - */ - if (type != FLUSH_KEEP) - goto restart; - } - if (last_in_flush) - { - /* - There are no blocks to be flushed by this thread, but blocks in - flush by other threads. Wait until one of the blocks is flushed. - Re-check the condition for last_in_flush. We may have unlocked - the cache_lock in flush_cached_blocks(). The state of the block - could have changed. - */ - if (last_in_flush->status & BLOCK_IN_FLUSH) - wait_on_queue(&last_in_flush->wqueue[COND_FOR_SAVED], - &keycache->cache_lock); - /* Be sure not to lose a block. They may be flushed in random order. */ - goto restart; - } - if (last_for_update) - { - /* - There are no blocks to be flushed by this thread, but blocks for - update by other threads. Wait until one of the blocks is updated. - Re-check the condition for last_for_update. We may have unlocked - the cache_lock in flush_cached_blocks(). The state of the block - could have changed. - */ - if (last_for_update->status & BLOCK_FOR_UPDATE) - wait_on_queue(&last_for_update->wqueue[COND_FOR_REQUESTED], - &keycache->cache_lock); - /* The block is now changed. Flush it. */ - goto restart; - } - - /* - Wait until the list of blocks in switch is empty. The threads that - are switching these blocks will relink them to clean file chains - while we wait and thus empty the 'first_in_switch' chain. - */ - while (first_in_switch) - { -#if defined(KEYCACHE_DEBUG) - cnt= 0; -#endif - wait_on_queue(&first_in_switch->wqueue[COND_FOR_SAVED], - &keycache->cache_lock); -#if defined(KEYCACHE_DEBUG) - cnt++; - KEYCACHE_DBUG_ASSERT(cnt <= keycache->blocks_used); -#endif - /* - Do not restart here. We have flushed all blocks that were - changed when entering this function and were not marked for - eviction. Other threads have now flushed all remaining blocks in - the course of their eviction. - */ - } - - if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE)) - { - BLOCK_LINK *last_for_update= NULL; - BLOCK_LINK *last_in_switch= NULL; - uint total_found= 0; - uint found; - - /* - Finally free all clean blocks for this file. - During resize this may be run by two threads in parallel. - */ - do - { - found= 0; - for (block= keycache->file_blocks[FILE_HASH(file)] ; - block ; - block= next) - { - /* Remember the next block. After freeing we cannot get at it. */ - next= block->next_changed; - - /* Changed blocks cannot appear in the file_blocks hash. */ - DBUG_ASSERT(!(block->status & BLOCK_CHANGED)); - if (block->hash_link->file == file) - { - /* We must skip blocks that will be changed. */ - if (block->status & BLOCK_FOR_UPDATE) - { - last_for_update= block; - continue; - } - - /* - We must not free blocks in eviction (BLOCK_IN_EVICTION | - BLOCK_IN_SWITCH) or blocks intended to be freed - (BLOCK_REASSIGNED). - */ - if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH | - BLOCK_REASSIGNED))) - { - struct st_hash_link *UNINIT_VAR(next_hash_link); - my_off_t UNINIT_VAR(next_diskpos); - File UNINIT_VAR(next_file); - uint UNINIT_VAR(next_status); - uint UNINIT_VAR(hash_requests); - - total_found++; - found++; - KEYCACHE_DBUG_ASSERT(found <= keycache->blocks_used); - - /* - Register a request. This unlinks the block from the LRU - ring and protects it against eviction. This is required - by free_block(). - */ - reg_requests(keycache, block, 1); - - /* - free_block() may need to wait for readers of the block. - This is the moment where the other thread can move the - 'next' block from the chain. free_block() needs to wait - if there are requests for the block pending. - */ - if (next && (hash_requests= block->hash_link->requests)) - { - /* Copy values from the 'next' block and its hash_link. */ - next_status= next->status; - next_hash_link= next->hash_link; - next_diskpos= next_hash_link->diskpos; - next_file= next_hash_link->file; - DBUG_ASSERT(next == next_hash_link->block); - } - - free_block(keycache, block); - /* - If we had to wait and the state of the 'next' block - changed, break the inner loop. 'next' may no longer be - part of the current chain. - - We do not want to break the loop after every free_block(), - not even only after waits. The chain might be quite long - and contain blocks for many files. Traversing it again and - again to find more blocks for this file could become quite - inefficient. - */ - if (next && hash_requests && - ((next_status != next->status) || - (next_hash_link != next->hash_link) || - (next_file != next_hash_link->file) || - (next_diskpos != next_hash_link->diskpos) || - (next != next_hash_link->block))) - break; - } - else - { - last_in_switch= block; - } - } - } /* end for block in file_blocks */ - } while (found); - - /* - If any clean block has been found, we may have waited for it to - become free. In this case it could be possible that another clean - block became dirty. This is possible if the write request existed - before the flush started (BLOCK_FOR_UPDATE). Re-check the hashes. - */ - if (total_found) - goto restart; - - /* - To avoid an infinite loop, wait until one of the blocks marked - for update is updated. - */ - if (last_for_update) - { - /* We did not wait. Block must not have changed status. */ - DBUG_ASSERT(last_for_update->status & BLOCK_FOR_UPDATE); - wait_on_queue(&last_for_update->wqueue[COND_FOR_REQUESTED], - &keycache->cache_lock); - goto restart; - } - - /* - To avoid an infinite loop wait until one of the blocks marked - for eviction is switched. - */ - if (last_in_switch) - { - /* We did not wait. Block must not have changed status. */ - DBUG_ASSERT(last_in_switch->status & (BLOCK_IN_EVICTION | - BLOCK_IN_SWITCH | - BLOCK_REASSIGNED)); - wait_on_queue(&last_in_switch->wqueue[COND_FOR_SAVED], - &keycache->cache_lock); - goto restart; - } - - } /* if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE)) */ - - } /* if (keycache->disk_blocks > 0 */ - -#ifndef DBUG_OFF - DBUG_EXECUTE("check_keycache", - test_key_cache(keycache, "end of flush_key_blocks", 0);); -#endif -err: - if (cache != cache_buff) - my_free(cache); - if (last_errno) - errno=last_errno; /* Return first error */ - DBUG_RETURN(last_errno != 0); -} - - -/* - Flush all blocks for a file to disk - - SYNOPSIS - - flush_key_blocks() - keycache pointer to a key cache data structure - file handler for the file to flush to - flush_type type of the flush - - RETURN - 0 ok - 1 error -*/ - -int flush_key_blocks(KEY_CACHE *keycache, - File file, enum flush_type type) -{ - int res= 0; - DBUG_ENTER("flush_key_blocks"); - DBUG_PRINT("enter", ("keycache: 0x%lx", (long) keycache)); - - if (!keycache->key_cache_inited) - DBUG_RETURN(0); - - keycache_pthread_mutex_lock(&keycache->cache_lock); - /* While waiting for lock, keycache could have been ended. */ - if (keycache->disk_blocks > 0) - { - inc_counter_for_resize_op(keycache); - res= flush_key_blocks_int(keycache, file, type); - dec_counter_for_resize_op(keycache); - } - keycache_pthread_mutex_unlock(&keycache->cache_lock); - DBUG_RETURN(res); -} - - -/* - Flush all blocks in the key cache to disk. - - SYNOPSIS - flush_all_key_blocks() - keycache pointer to key cache root structure - - DESCRIPTION - - Flushing of the whole key cache is done in two phases. - - 1. Flush all changed blocks, waiting for them if necessary. Loop - until there is no changed block left in the cache. - - 2. Free all clean blocks. Normally this means free all blocks. The - changed blocks were flushed in phase 1 and became clean. However we - may need to wait for blocks that are read by other threads. While we - wait, a clean block could become changed if that operation started - before the resize operation started. To be safe we must restart at - phase 1. - - When we can run through the changed_blocks and file_blocks hashes - without finding a block any more, then we are done. - - Note that we hold keycache->cache_lock all the time unless we need - to wait for something. - - RETURN - 0 OK - != 0 Error -*/ - -static int flush_all_key_blocks(KEY_CACHE *keycache) -{ - BLOCK_LINK *block; - uint total_found; - uint found; - uint idx; - DBUG_ENTER("flush_all_key_blocks"); - - do - { - mysql_mutex_assert_owner(&keycache->cache_lock); - total_found= 0; - - /* - Phase1: Flush all changed blocks, waiting for them if necessary. - Loop until there is no changed block left in the cache. - */ - do - { - found= 0; - /* Step over the whole changed_blocks hash array. */ - for (idx= 0; idx < CHANGED_BLOCKS_HASH; idx++) - { - /* - If an array element is non-empty, use the first block from its - chain to find a file for flush. All changed blocks for this - file are flushed. So the same block will not appear at this - place again with the next iteration. New writes for blocks are - not accepted during the flush. If multiple files share the - same hash bucket, one of them will be flushed per iteration - of the outer loop of phase 1. - */ - if ((block= keycache->changed_blocks[idx])) - { - found++; - /* - Flush dirty blocks but do not free them yet. They can be used - for reading until all other blocks are flushed too. - */ - if (flush_key_blocks_int(keycache, block->hash_link->file, - FLUSH_FORCE_WRITE)) - DBUG_RETURN(1); - } - } - - } while (found); - - /* - Phase 2: Free all clean blocks. Normally this means free all - blocks. The changed blocks were flushed in phase 1 and became - clean. However we may need to wait for blocks that are read by - other threads. While we wait, a clean block could become changed - if that operation started before the resize operation started. To - be safe we must restart at phase 1. - */ - do - { - found= 0; - /* Step over the whole file_blocks hash array. */ - for (idx= 0; idx < CHANGED_BLOCKS_HASH; idx++) - { - /* - If an array element is non-empty, use the first block from its - chain to find a file for flush. All blocks for this file are - freed. So the same block will not appear at this place again - with the next iteration. If multiple files share the - same hash bucket, one of them will be flushed per iteration - of the outer loop of phase 2. - */ - if ((block= keycache->file_blocks[idx])) - { - total_found++; - found++; - if (flush_key_blocks_int(keycache, block->hash_link->file, - FLUSH_RELEASE)) - DBUG_RETURN(1); - } - } - - } while (found); - - /* - If any clean block has been found, we may have waited for it to - become free. In this case it could be possible that another clean - block became dirty. This is possible if the write request existed - before the resize started (BLOCK_FOR_UPDATE). Re-check the hashes. - */ - } while (total_found); - -#ifndef DBUG_OFF - /* Now there should not exist any block any more. */ - for (idx= 0; idx < CHANGED_BLOCKS_HASH; idx++) - { - DBUG_ASSERT(!keycache->changed_blocks[idx]); - DBUG_ASSERT(!keycache->file_blocks[idx]); - } -#endif - - DBUG_RETURN(0); -} - - -/* - Reset the counters of a key cache. - - SYNOPSIS - reset_key_cache_counters() - name the name of a key cache - key_cache pointer to the key kache to be reset - - DESCRIPTION - This procedure is used by process_key_caches() to reset the counters of all - currently used key caches, both the default one and the named ones. - - RETURN - 0 on success (always because it can't fail) -*/ - -int reset_key_cache_counters(const char *name __attribute__((unused)), - KEY_CACHE *key_cache) -{ - DBUG_ENTER("reset_key_cache_counters"); - if (!key_cache->key_cache_inited) - { - DBUG_PRINT("info", ("Key cache %s not initialized.", name)); - DBUG_RETURN(0); - } - DBUG_PRINT("info", ("Resetting counters for key cache %s.", name)); - - key_cache->global_blocks_changed= 0; /* Key_blocks_not_flushed */ - key_cache->global_cache_r_requests= 0; /* Key_read_requests */ - key_cache->global_cache_read= 0; /* Key_reads */ - key_cache->global_cache_w_requests= 0; /* Key_write_requests */ - key_cache->global_cache_write= 0; /* Key_writes */ - DBUG_RETURN(0); -} - - -#ifndef DBUG_OFF -/* - Test if disk-cache is ok -*/ -static void test_key_cache(KEY_CACHE *keycache __attribute__((unused)), - const char *where __attribute__((unused)), - my_bool lock __attribute__((unused))) -{ - /* TODO */ -} -#endif - -#if defined(KEYCACHE_TIMEOUT) - -#define KEYCACHE_DUMP_FILE "keycache_dump.txt" -#define MAX_QUEUE_LEN 100 - - -static void keycache_dump(KEY_CACHE *keycache) -{ - FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w"); - struct st_my_thread_var *last; - struct st_my_thread_var *thread; - BLOCK_LINK *block; - HASH_LINK *hash_link; - KEYCACHE_PAGE *page; - uint i; - - fprintf(keycache_dump_file, "thread:%u\n", thread->id); - - i=0; - thread=last=waiting_for_hash_link.last_thread; - fprintf(keycache_dump_file, "queue of threads waiting for hash link\n"); - if (thread) - do - { - thread=thread->next; - page= (KEYCACHE_PAGE *) thread->opt_info; - fprintf(keycache_dump_file, - "thread:%u, (file,filepos)=(%u,%lu)\n", - thread->id,(uint) page->file,(ulong) page->filepos); - if (++i == MAX_QUEUE_LEN) - break; - } - while (thread != last); - - i=0; - thread=last=waiting_for_block.last_thread; - fprintf(keycache_dump_file, "queue of threads waiting for block\n"); - if (thread) - do - { - thread=thread->next; - hash_link= (HASH_LINK *) thread->opt_info; - fprintf(keycache_dump_file, - "thread:%u hash_link:%u (file,filepos)=(%u,%lu)\n", - thread->id, (uint) HASH_LINK_NUMBER(hash_link), - (uint) hash_link->file,(ulong) hash_link->diskpos); - if (++i == MAX_QUEUE_LEN) - break; - } - while (thread != last); - - for (i=0 ; i< keycache->blocks_used ; i++) - { - int j; - block= &keycache->block_root[i]; - hash_link= block->hash_link; - fprintf(keycache_dump_file, - "block:%u hash_link:%d status:%x #requests=%u waiting_for_readers:%d\n", - i, (int) (hash_link ? HASH_LINK_NUMBER(hash_link) : -1), - block->status, block->requests, block->condvar ? 1 : 0); - for (j=0 ; j < 2; j++) - { - KEYCACHE_WQUEUE *wqueue=&block->wqueue[j]; - thread= last= wqueue->last_thread; - fprintf(keycache_dump_file, "queue #%d\n", j); - if (thread) - { - do - { - thread=thread->next; - fprintf(keycache_dump_file, - "thread:%u\n", thread->id); - if (++i == MAX_QUEUE_LEN) - break; - } - while (thread != last); - } - } - } - fprintf(keycache_dump_file, "LRU chain:"); - block= keycache= used_last; - if (block) - { - do - { - block= block->next_used; - fprintf(keycache_dump_file, - "block:%u, ", BLOCK_NUMBER(block)); - } - while (block != keycache->used_last); - } - fprintf(keycache_dump_file, "\n"); - - fclose(keycache_dump_file); -} - -#endif /* defined(KEYCACHE_TIMEOUT) */ - -#if defined(KEYCACHE_TIMEOUT) && !defined(__WIN__) - - -static int keycache_pthread_cond_wait(mysql_cond_t *cond, - mysql_mutex_t *mutex) -{ - int rc; - struct timeval now; /* time when we started waiting */ - struct timespec timeout; /* timeout value for the wait function */ - struct timezone tz; -#if defined(KEYCACHE_DEBUG) - int cnt=0; -#endif - - /* Get current time */ - gettimeofday(&now, &tz); - /* Prepare timeout value */ - timeout.tv_sec= now.tv_sec + KEYCACHE_TIMEOUT; - /* - timeval uses microseconds. - timespec uses nanoseconds. - 1 nanosecond = 1000 micro seconds - */ - timeout.tv_nsec= now.tv_usec * 1000; - KEYCACHE_THREAD_TRACE_END("started waiting"); -#if defined(KEYCACHE_DEBUG) - cnt++; - if (cnt % 100 == 0) - fprintf(keycache_debug_log, "waiting...\n"); - fflush(keycache_debug_log); -#endif - rc= mysql_cond_timedwait(cond, mutex, &timeout); - KEYCACHE_THREAD_TRACE_BEGIN("finished waiting"); - if (rc == ETIMEDOUT || rc == ETIME) - { -#if defined(KEYCACHE_DEBUG) - fprintf(keycache_debug_log,"aborted by keycache timeout\n"); - fclose(keycache_debug_log); - abort(); -#endif - keycache_dump(); - } - -#if defined(KEYCACHE_DEBUG) - KEYCACHE_DBUG_ASSERT(rc != ETIMEDOUT); -#else - assert(rc != ETIMEDOUT); -#endif - return rc; -} -#else -#if defined(KEYCACHE_DEBUG) -static int keycache_pthread_cond_wait(mysql_cond_t *cond, - mysql_mutex_t *mutex) -{ - int rc; - KEYCACHE_THREAD_TRACE_END("started waiting"); - rc= mysql_cond_wait(cond, mutex); - KEYCACHE_THREAD_TRACE_BEGIN("finished waiting"); - return rc; -} -#endif -#endif /* defined(KEYCACHE_TIMEOUT) && !defined(__WIN__) */ - -#if defined(KEYCACHE_DEBUG) - - -static int keycache_pthread_mutex_lock(mysql_mutex_t *mutex) -{ - int rc; - rc= mysql_mutex_lock(mutex); - KEYCACHE_THREAD_TRACE_BEGIN(""); - return rc; -} - - -static void keycache_pthread_mutex_unlock(mysql_mutex_t *mutex) -{ - KEYCACHE_THREAD_TRACE_END(""); - mysql_mutex_unlock(mutex); -} - - -static int keycache_pthread_cond_signal(mysql_cond_t *cond) -{ - int rc; - KEYCACHE_THREAD_TRACE("signal"); - rc= mysql_cond_signal(cond); - return rc; -} - - -#if defined(KEYCACHE_DEBUG_LOG) - - -static void keycache_debug_print(const char * fmt,...) -{ - va_list args; - va_start(args,fmt); - if (keycache_debug_log) - { - (void) vfprintf(keycache_debug_log, fmt, args); - (void) fputc('\n',keycache_debug_log); - } - va_end(args); -} -#endif /* defined(KEYCACHE_DEBUG_LOG) */ - -#if defined(KEYCACHE_DEBUG_LOG) - - -void keycache_debug_log_close(void) -{ - if (keycache_debug_log) - fclose(keycache_debug_log); -} -#endif /* defined(KEYCACHE_DEBUG_LOG) */ - -#endif /* defined(KEYCACHE_DEBUG) */ - -#if !defined(DBUG_OFF) -#define F_B_PRT(_f_, _v_) DBUG_PRINT("assert_fail", (_f_, _v_)) - -static int fail_block(BLOCK_LINK *block) -{ - F_B_PRT("block->next_used: %lx\n", (ulong) block->next_used); - F_B_PRT("block->prev_used: %lx\n", (ulong) block->prev_used); - F_B_PRT("block->next_changed: %lx\n", (ulong) block->next_changed); - F_B_PRT("block->prev_changed: %lx\n", (ulong) block->prev_changed); - F_B_PRT("block->hash_link: %lx\n", (ulong) block->hash_link); - F_B_PRT("block->status: %u\n", block->status); - F_B_PRT("block->length: %u\n", block->length); - F_B_PRT("block->offset: %u\n", block->offset); - F_B_PRT("block->requests: %u\n", block->requests); - F_B_PRT("block->temperature: %u\n", block->temperature); - return 0; /* Let the assert fail. */ -} - -static int fail_hlink(HASH_LINK *hlink) -{ - F_B_PRT("hlink->next: %lx\n", (ulong) hlink->next); - F_B_PRT("hlink->prev: %lx\n", (ulong) hlink->prev); - F_B_PRT("hlink->block: %lx\n", (ulong) hlink->block); - F_B_PRT("hlink->diskpos: %lu\n", (ulong) hlink->diskpos); - F_B_PRT("hlink->file: %d\n", hlink->file); - return 0; /* Let the assert fail. */ -} - -static int cache_empty(KEY_CACHE *keycache) -{ - int errcnt= 0; - int idx; - if (keycache->disk_blocks <= 0) - return 1; - for (idx= 0; idx < keycache->disk_blocks; idx++) - { - BLOCK_LINK *block= keycache->block_root + idx; - if (block->status || block->requests || block->hash_link) - { - fprintf(stderr, "block index: %u\n", idx); - fail_block(block); - errcnt++; - } - } - for (idx= 0; idx < keycache->hash_links; idx++) - { - HASH_LINK *hash_link= keycache->hash_link_root + idx; - if (hash_link->requests || hash_link->block) - { - fprintf(stderr, "hash_link index: %u\n", idx); - fail_hlink(hash_link); - errcnt++; - } - } - if (errcnt) - { - fprintf(stderr, "blocks: %d used: %lu\n", - keycache->disk_blocks, keycache->blocks_used); - fprintf(stderr, "hash_links: %d used: %d\n", - keycache->hash_links, keycache->hash_links_used); - fprintf(stderr, "\n"); - } - return !errcnt; -} -#endif - diff --git a/dep/mysqllite/mysys/mf_keycaches.c b/dep/mysqllite/mysys/mf_keycaches.c deleted file mode 100644 index 93b7eab4561..00000000000 --- a/dep/mysqllite/mysys/mf_keycaches.c +++ /dev/null @@ -1,361 +0,0 @@ -/* Copyright (C) 2003 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 */ - -/* - Handling of multiple key caches - - The idea is to have a thread safe hash on the table name, - with a default key cache value that is returned if the table name is not in - the cache. -*/ - -#include "mysys_priv.h" -#include <keycache.h> -#include <hash.h> -#include <m_string.h> - -/***************************************************************************** - General functions to handle SAFE_HASH objects. - - A SAFE_HASH object is used to store the hash, the mutex and default value - needed by the rest of the key cache code. - This is a separate struct to make it easy to later reuse the code for other - purposes - - All entries are linked in a list to allow us to traverse all elements - and delete selected ones. (HASH doesn't allow any easy ways to do this). -*****************************************************************************/ - -/* - Struct to store a key and pointer to object -*/ - -typedef struct st_safe_hash_entry -{ - uchar *key; - uint length; - uchar *data; - struct st_safe_hash_entry *next, **prev; -} SAFE_HASH_ENTRY; - - -typedef struct st_safe_hash_with_default -{ - rw_lock_t mutex; - HASH hash; - uchar *default_value; - SAFE_HASH_ENTRY *root; -} SAFE_HASH; - - -/* - Free a SAFE_HASH_ENTRY - - This function is called by the hash object on delete -*/ - -static void safe_hash_entry_free(SAFE_HASH_ENTRY *entry) -{ - DBUG_ENTER("free_assign_entry"); - my_free(entry); - DBUG_VOID_RETURN; -} - - -/* Get key and length for a SAFE_HASH_ENTRY */ - -static uchar *safe_hash_entry_get(SAFE_HASH_ENTRY *entry, size_t *length, - my_bool not_used __attribute__((unused))) -{ - *length=entry->length; - return (uchar*) entry->key; -} - - -/* - Init a SAFE_HASH object - - SYNOPSIS - safe_hash_init() - hash safe_hash handler - elements Expected max number of elements - default_value default value - - NOTES - In case of error we set hash->default_value to 0 to allow one to call - safe_hash_free on an object that couldn't be initialized. - - RETURN - 0 ok - 1 error -*/ - -static my_bool safe_hash_init(SAFE_HASH *hash, uint elements, - uchar *default_value) -{ - DBUG_ENTER("safe_hash"); - if (my_hash_init(&hash->hash, &my_charset_bin, elements, - 0, 0, (my_hash_get_key) safe_hash_entry_get, - (void (*)(void*)) safe_hash_entry_free, 0)) - { - hash->default_value= 0; - DBUG_RETURN(1); - } - my_rwlock_init(&hash->mutex, 0); - hash->default_value= default_value; - hash->root= 0; - DBUG_RETURN(0); -} - - -/* - Free a SAFE_HASH object - - NOTES - This is safe to call on any object that has been sent to safe_hash_init() -*/ - -static void safe_hash_free(SAFE_HASH *hash) -{ - /* - Test if safe_hash_init succeeded. This will also guard us against multiple - free calls. - */ - if (hash->default_value) - { - my_hash_free(&hash->hash); - rwlock_destroy(&hash->mutex); - hash->default_value=0; - } -} - -/* - Return the value stored for a key or default value if no key -*/ - -static uchar *safe_hash_search(SAFE_HASH *hash, const uchar *key, uint length) -{ - uchar *result; - DBUG_ENTER("safe_hash_search"); - rw_rdlock(&hash->mutex); - result= my_hash_search(&hash->hash, key, length); - rw_unlock(&hash->mutex); - if (!result) - result= hash->default_value; - else - result= ((SAFE_HASH_ENTRY*) result)->data; - DBUG_PRINT("exit",("data: 0x%lx", (long) result)); - DBUG_RETURN(result); -} - - -/* - Associate a key with some data - - SYONOPSIS - safe_hash_set() - hash Hash handle - key key (path to table etc..) - length Length of key - data data to to associate with the data - - NOTES - This can be used both to insert a new entry and change an existing - entry. - If one associates a key with the default key cache, the key is deleted - - RETURN - 0 ok - 1 error (Can only be EOM). In this case my_message() is called. -*/ - -static my_bool safe_hash_set(SAFE_HASH *hash, const uchar *key, uint length, - uchar *data) -{ - SAFE_HASH_ENTRY *entry; - my_bool error= 0; - DBUG_ENTER("safe_hash_set"); - DBUG_PRINT("enter",("key: %.*s data: 0x%lx", length, key, (long) data)); - - rw_wrlock(&hash->mutex); - entry= (SAFE_HASH_ENTRY*) my_hash_search(&hash->hash, key, length); - - if (data == hash->default_value) - { - /* - The key is to be associated with the default entry. In this case - we can just delete the entry (if it existed) from the hash as a - search will return the default entry - */ - if (!entry) /* nothing to do */ - goto end; - /* unlink entry from list */ - if ((*entry->prev= entry->next)) - entry->next->prev= entry->prev; - my_hash_delete(&hash->hash, (uchar*) entry); - goto end; - } - if (entry) - { - /* Entry existed; Just change the pointer to point at the new data */ - entry->data= data; - } - else - { - if (!(entry= (SAFE_HASH_ENTRY *) my_malloc(sizeof(*entry) + length, - MYF(MY_WME)))) - { - error= 1; - goto end; - } - entry->key= (uchar*) (entry +1); - memcpy((char*) entry->key, (char*) key, length); - entry->length= length; - entry->data= data; - /* Link entry to list */ - if ((entry->next= hash->root)) - entry->next->prev= &entry->next; - entry->prev= &hash->root; - hash->root= entry; - if (my_hash_insert(&hash->hash, (uchar*) entry)) - { - /* This can only happen if hash got out of memory */ - my_free(entry); - error= 1; - goto end; - } - } - -end: - rw_unlock(&hash->mutex); - DBUG_RETURN(error); -} - - -/* - Change all entres with one data value to another data value - - SYONOPSIS - safe_hash_change() - hash Hash handle - old_data Old data - new_data Change all 'old_data' to this - - NOTES - We use the linked list to traverse all elements in the hash as - this allows us to delete elements in the case where 'new_data' is the - default value. -*/ - -static void safe_hash_change(SAFE_HASH *hash, uchar *old_data, uchar *new_data) -{ - SAFE_HASH_ENTRY *entry, *next; - DBUG_ENTER("safe_hash_set"); - - rw_wrlock(&hash->mutex); - - for (entry= hash->root ; entry ; entry= next) - { - next= entry->next; - if (entry->data == old_data) - { - if (new_data == hash->default_value) - { - if ((*entry->prev= entry->next)) - entry->next->prev= entry->prev; - my_hash_delete(&hash->hash, (uchar*) entry); - } - else - entry->data= new_data; - } - } - - rw_unlock(&hash->mutex); - DBUG_VOID_RETURN; -} - - -/***************************************************************************** - Functions to handle the key cache objects -*****************************************************************************/ - -/* Variable to store all key cache objects */ -static SAFE_HASH key_cache_hash; - - -my_bool multi_keycache_init(void) -{ - return safe_hash_init(&key_cache_hash, 16, (uchar*) dflt_key_cache); -} - - -void multi_keycache_free(void) -{ - safe_hash_free(&key_cache_hash); -} - -/* - Get a key cache to be used for a specific table. - - SYNOPSIS - multi_key_cache_search() - key key to find (usually table path) - uint length Length of key. - - NOTES - This function is coded in such a way that we will return the - default key cache even if one never called multi_keycache_init. - This will ensure that it works with old MyISAM clients. - - RETURN - key cache to use -*/ - -KEY_CACHE *multi_key_cache_search(uchar *key, uint length) -{ - if (!key_cache_hash.hash.records) - return dflt_key_cache; - return (KEY_CACHE*) safe_hash_search(&key_cache_hash, key, length); -} - - -/* - Assosiate a key cache with a key - - - SYONOPSIS - multi_key_cache_set() - key key (path to table etc..) - length Length of key - key_cache cache to assococite with the table - - NOTES - This can be used both to insert a new entry and change an existing - entry -*/ - - -my_bool multi_key_cache_set(const uchar *key, uint length, - KEY_CACHE *key_cache) -{ - return safe_hash_set(&key_cache_hash, key, length, (uchar*) key_cache); -} - - -void multi_key_cache_change(KEY_CACHE *old_data, - KEY_CACHE *new_data) -{ - safe_hash_change(&key_cache_hash, (uchar*) old_data, (uchar*) new_data); -} diff --git a/dep/mysqllite/mysys/mf_loadpath.c b/dep/mysqllite/mysys/mf_loadpath.c deleted file mode 100644 index 9350babc176..00000000000 --- a/dep/mysqllite/mysys/mf_loadpath.c +++ /dev/null @@ -1,55 +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 <m_string.h> - - /* Returns full load-path for a file. to may be = path */ - /* if path is a hard-path return path */ - /* if path starts with home-dir return path */ - /* if path starts with current dir or parent-dir unpack path */ - /* if there is no path, prepend with own_path_prefix if given */ - /* else unpack path according to current dir */ - -char * my_load_path(char * to, const char *path, - const char *own_path_prefix) -{ - char buff[FN_REFLEN]; - int is_cur; - DBUG_ENTER("my_load_path"); - DBUG_PRINT("enter",("path: %s prefix: %s",path, - own_path_prefix ? own_path_prefix : "")); - - if ((path[0] == FN_HOMELIB && path[1] == FN_LIBCHAR) || - test_if_hard_path(path)) - (void) strnmov(buff, path, FN_REFLEN); - else if ((is_cur=(path[0] == FN_CURLIB && path[1] == FN_LIBCHAR)) || - (is_prefix(path,FN_PARENTDIR)) || - ! own_path_prefix) - { - if (is_cur) - is_cur=2; /* Remove current dir */ - if (! my_getwd(buff,(uint) (FN_REFLEN-strlen(path)+is_cur),MYF(0))) - (void) strncat(buff, path+is_cur, FN_REFLEN-1); - else - (void) strnmov(buff, path, FN_REFLEN); /* Return org file name */ - } - else - (void) strxnmov(buff, FN_REFLEN, own_path_prefix, path, NullS); - strnmov(to, buff, FN_REFLEN); - to[FN_REFLEN-1]= '\0'; - DBUG_PRINT("exit",("to: %s",to)); - DBUG_RETURN(to); -} /* my_load_path */ diff --git a/dep/mysqllite/mysys/mf_pack.c b/dep/mysqllite/mysys/mf_pack.c deleted file mode 100644 index 292cd8c0454..00000000000 --- a/dep/mysqllite/mysys/mf_pack.c +++ /dev/null @@ -1,460 +0,0 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. - - 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 <m_string.h> -#ifdef HAVE_PWD_H -#include <pwd.h> -#endif - -static char * expand_tilde(char **path); - - /* Pack a dirname ; Changes HOME to ~/ and current dev to ./ */ - /* from is a dirname (from dirname() ?) ending with FN_LIBCHAR */ - /* to may be == from */ - -void pack_dirname(char * to, const char *from) -{ - int cwd_err; - size_t d_length,length,UNINIT_VAR(buff_length); - char * start; - char buff[FN_REFLEN]; - DBUG_ENTER("pack_dirname"); - - (void) intern_filename(to,from); /* Change to intern name */ - -#ifdef FN_DEVCHAR - if ((start=strrchr(to,FN_DEVCHAR)) != 0) /* Skip device part */ - start++; - else -#endif - start=to; - - if (!(cwd_err= my_getwd(buff,FN_REFLEN,MYF(0)))) - { - buff_length= strlen(buff); - d_length= (size_t) (start-to); - if ((start == to || - (buff_length == d_length && !memcmp(buff,start,d_length))) && - *start != FN_LIBCHAR && *start) - { /* Put current dir before */ - bchange((uchar*) to, d_length, (uchar*) buff, buff_length, strlen(to)+1); - } - } - - if ((d_length= cleanup_dirname(to,to)) != 0) - { - length=0; - if (home_dir) - { - length= strlen(home_dir); - if (home_dir[length-1] == FN_LIBCHAR) - length--; /* Don't test last '/' */ - } - if (length > 1 && length < d_length) - { /* test if /xx/yy -> ~/yy */ - if (memcmp(to,home_dir,length) == 0 && to[length] == FN_LIBCHAR) - { - to[0]=FN_HOMELIB; /* Filename begins with ~ */ - (void) strmov_overlapp(to+1,to+length); - } - } - if (! cwd_err) - { /* Test if cwd is ~/... */ - if (length > 1 && length < buff_length) - { - if (memcmp(buff,home_dir,length) == 0 && buff[length] == FN_LIBCHAR) - { - buff[0]=FN_HOMELIB; - (void) strmov_overlapp(buff+1,buff+length); - } - } - if (is_prefix(to,buff)) - { - length= strlen(buff); - if (to[length]) - (void) strmov_overlapp(to,to+length); /* Remove everything before */ - else - { - to[0]= FN_CURLIB; /* Put ./ instead of cwd */ - to[1]= FN_LIBCHAR; - to[2]= '\0'; - } - } - } - } - DBUG_PRINT("exit",("to: '%s'",to)); - DBUG_VOID_RETURN; -} /* pack_dirname */ - - -/* - remove unwanted chars from dirname - - 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 -*/ - -size_t cleanup_dirname(register char *to, const char *from) -{ - reg5 size_t length; - reg2 char * pos; - reg3 char * from_ptr; - reg4 char * start; - char parent[5], /* for "FN_PARENTDIR" */ - buff[FN_REFLEN+1],*end_parentdir; -#ifdef BACKSLASH_MBTAIL - CHARSET_INFO *fs= fs_character_set(); -#endif - DBUG_ENTER("cleanup_dirname"); - DBUG_PRINT("enter",("from: '%s'",from)); - - start=buff; - from_ptr=(char *) from; -#ifdef FN_DEVCHAR - if ((pos=strrchr(from_ptr,FN_DEVCHAR)) != 0) - { /* Skip device part */ - length=(size_t) (pos-from_ptr)+1; - start=strnmov(buff,from_ptr,length); from_ptr+=length; - } -#endif - - parent[0]=FN_LIBCHAR; - length=(size_t) (strmov(parent+1,FN_PARENTDIR)-parent); - for (pos=start ; (*pos= *from_ptr++) != 0 ; pos++) - { -#ifdef BACKSLASH_MBTAIL - uint l; - if (use_mb(fs) && (l= my_ismbchar(fs, from_ptr - 1, from_ptr + 2))) - { - for (l-- ; l ; *++pos= *from_ptr++, l--); - start= pos + 1; /* Don't look inside multi-byte char */ - continue; - } -#endif - if (*pos == '/') - *pos = FN_LIBCHAR; - if (*pos == FN_LIBCHAR) - { - if ((size_t) (pos-start) > length && memcmp(pos-length,parent,length) == 0) - { /* If .../../; skip prev */ - pos-=length; - if (pos != start) - { /* not /../ */ - pos--; - if (*pos == FN_HOMELIB && (pos == start || pos[-1] == FN_LIBCHAR)) - { - if (!home_dir) - { - pos+=length+1; /* Don't unpack ~/.. */ - continue; - } - pos=strmov(buff,home_dir)-1; /* Unpacks ~/.. */ - if (*pos == FN_LIBCHAR) - pos--; /* home ended with '/' */ - } - if (*pos == FN_CURLIB && (pos == start || pos[-1] == FN_LIBCHAR)) - { - if (my_getwd(curr_dir,FN_REFLEN,MYF(0))) - { - pos+=length+1; /* Don't unpack ./.. */ - continue; - } - pos=strmov(buff,curr_dir)-1; /* Unpacks ./.. */ - if (*pos == FN_LIBCHAR) - pos--; /* home ended with '/' */ - } - end_parentdir=pos; - while (pos >= start && *pos != FN_LIBCHAR) /* remove prev dir */ - pos--; - if (pos[1] == FN_HOMELIB || - (pos > start && memcmp(pos, parent, length) == 0)) - { /* Don't remove ~user/ */ - pos=strmov(end_parentdir+1,parent); - *pos=FN_LIBCHAR; - continue; - } - } - } - else if ((size_t) (pos-start) == length-1 && - !memcmp(start,parent+1,length-1)) - start=pos; /* Starts with "../" */ - else if (pos-start > 0 && pos[-1] == FN_LIBCHAR) - { -#ifdef FN_NETWORK_DRIVES - if (pos-start != 1) -#endif - pos--; /* Remove dupplicate '/' */ - } - else if (pos-start > 1 && pos[-1] == FN_CURLIB && pos[-2] == FN_LIBCHAR) - pos-=2; /* Skip /./ */ - else if (pos > buff+1 && pos[-1] == FN_HOMELIB && pos[-2] == FN_LIBCHAR) - { /* Found ..../~/ */ - buff[0]=FN_HOMELIB; - buff[1]=FN_LIBCHAR; - start=buff; pos=buff+1; - } - } - } - (void) strmov(to,buff); - DBUG_PRINT("exit",("to: '%s'",to)); - DBUG_RETURN((size_t) (pos-buff)); -} /* cleanup_dirname */ - - -/* - On system where you don't have symbolic links, the following - code will allow you to create a file: - directory-name.sym that should contain the real path - to the directory. This will be used if the directory name - doesn't exists -*/ - - -my_bool my_use_symdir=0; /* Set this if you want to use symdirs */ - -#ifdef USE_SYMDIR -void symdirget(char *dir) -{ - char buff[FN_REFLEN+1]; - char *pos=strend(dir); - if (dir[0] && pos[-1] != FN_DEVCHAR && my_access(dir, F_OK)) - { - File file; - size_t length; - char temp= *(--pos); /* May be "/" or "\" */ - strmov(pos,".sym"); - file= my_open(dir, O_RDONLY, MYF(0)); - *pos++=temp; *pos=0; /* Restore old filename */ - if (file >= 0) - { - if ((length= my_read(file, buff, sizeof(buff) - 1, MYF(0))) > 0) - { - for (pos= buff + length ; - pos > buff && (iscntrl(pos[-1]) || isspace(pos[-1])) ; - pos --); - - /* Ensure that the symlink ends with the directory symbol */ - if (pos == buff || pos[-1] != FN_LIBCHAR) - *pos++=FN_LIBCHAR; - - strmake(dir,buff, (size_t) (pos-buff)); - } - my_close(file, MYF(0)); - } - } -} -#endif /* USE_SYMDIR */ - - -/** - Convert a directory name to a format which can be compared as strings - - @param to result buffer, FN_REFLEN chars in length; may be == from - @param from 'packed' directory name, in whatever format - @returns size of the normalized name - - @details - - Ensures that last char is FN_LIBCHAR, unless it is FN_DEVCHAR - - Uses cleanup_dirname - - It does *not* expand ~/ (although, see cleanup_dirname). Nor does it do - any case folding. All case-insensitive normalization should be done by - the caller. -*/ - -size_t normalize_dirname(char *to, const char *from) -{ - size_t length; - char buff[FN_REFLEN]; - DBUG_ENTER("normalize_dirname"); - - /* - Despite the name, this actually converts the name to the system's - format (TODO: name this properly). - */ - (void) intern_filename(buff, from); - length= strlen(buff); /* Fix that '/' is last */ - if (length && -#ifdef FN_DEVCHAR - buff[length - 1] != FN_DEVCHAR && -#endif - buff[length - 1] != FN_LIBCHAR && buff[length - 1] != '/') - { - /* we need reserve 2 bytes for the trailing slash and the zero */ - if (length >= sizeof (buff) - 1) - length= sizeof (buff) - 2; - buff[length]= FN_LIBCHAR; - buff[length + 1]= '\0'; - } - - length=cleanup_dirname(to, buff); - - DBUG_RETURN(length); -} - - -/** - Fixes a directory name so that can be used by open() - - @param to Result buffer, FN_REFLEN characters. May be == from - @param from 'Packed' directory name (may contain ~) - - @details - - Uses normalize_dirname() - - Expands ~/... to home_dir/... - - Resolves MySQL's fake "foo.sym" symbolic directory names (if USE_SYMDIR) - - Changes a UNIX filename to system filename (replaces / with \ on windows) - - @returns - Length of new directory name (= length of to) -*/ - -size_t unpack_dirname(char * to, const char *from) -{ - size_t length, h_length; - char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion; - DBUG_ENTER("unpack_dirname"); - - length= normalize_dirname(buff, from); - - if (buff[0] == FN_HOMELIB) - { - suffix=buff+1; tilde_expansion=expand_tilde(&suffix); - if (tilde_expansion) - { - length-= (size_t) (suffix-buff)-1; - if (length+(h_length= strlen(tilde_expansion)) <= FN_REFLEN) - { - if ((h_length > 0) && (tilde_expansion[h_length-1] == FN_LIBCHAR)) - h_length--; - if (buff+h_length < suffix) - bmove(buff+h_length,suffix,length); - else - bmove_upp((uchar*) buff+h_length+length, (uchar*) suffix+length, length); - bmove(buff,tilde_expansion,h_length); - } - } - } -#ifdef USE_SYMDIR - if (my_use_symdir) - symdirget(buff); -#endif - DBUG_RETURN(system_filename(to,buff)); /* Fix for open */ -} /* unpack_dirname */ - - - /* Expand tilde to home or user-directory */ - /* Path is reset to point at FN_LIBCHAR after ~xxx */ - -static char * expand_tilde(char **path) -{ - if (path[0][0] == FN_LIBCHAR) - return home_dir; /* ~/ expanded to home */ -#ifdef HAVE_GETPWNAM - { - char *str,save; - struct passwd *user_entry; - - if (!(str=strchr(*path,FN_LIBCHAR))) - str=strend(*path); - save= *str; *str= '\0'; - user_entry=getpwnam(*path); - *str=save; - endpwent(); - if (user_entry) - { - *path=str; - return user_entry->pw_dir; - } - } -#endif - return (char *) 0; -} - - -/* - Fix filename so it can be used by open, create - - SYNOPSIS - unpack_filename() - to Store result here. Must be at least of size FN_REFLEN. - from Filename in unix format (with ~) - - RETURN - # length of to - - NOTES - to may be == from - ~ will only be expanded if total length < FN_REFLEN -*/ - - -size_t unpack_filename(char * to, const char *from) -{ - size_t length, n_length, buff_length; - char buff[FN_REFLEN]; - DBUG_ENTER("unpack_filename"); - - length=dirname_part(buff, from, &buff_length);/* copy & convert dirname */ - n_length=unpack_dirname(buff,buff); - if (n_length+strlen(from+length) < FN_REFLEN) - { - (void) strmov(buff+n_length,from+length); - length= system_filename(to,buff); /* Fix to usably filename */ - } - else - length= system_filename(to,from); /* Fix to usably filename */ - DBUG_RETURN(length); -} /* unpack_filename */ - - - /* Convert filename (unix standard) to system standard */ - /* Used before system command's like open(), create() .. */ - /* Returns used length of to; total length should be FN_REFLEN */ - -size_t system_filename(char *to, const char *from) -{ - return (size_t) (strmake(to,from,FN_REFLEN-1)-to); -} - - /* Fix a filename to intern (UNIX format) */ - -char *intern_filename(char *to, const char *from) -{ - size_t length, to_length; - char buff[FN_REFLEN]; - if (from == to) - { /* Dirname may destroy from */ - strmov(buff,from); - from=buff; - } - length= dirname_part(to, from, &to_length); /* Copy dirname & fix chars */ - (void) strmov(to + to_length,from+length); - return (to); -} /* intern_filename */ diff --git a/dep/mysqllite/mysys/mf_path.c b/dep/mysqllite/mysys/mf_path.c deleted file mode 100644 index 92cb62e6827..00000000000 --- a/dep/mysqllite/mysys/mf_path.c +++ /dev/null @@ -1,120 +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 <m_string.h> - -static char *find_file_in_path(char *to,const char *name); - - /* Finds where program can find it's files. - pre_pathname is found by first locking at progname (argv[0]). - if progname contains path the path is returned. - else if progname is found in path, return it - else if progname is given and POSIX environment variable "_" is set - then path is taken from "_". - If filename doesn't contain a path append MY_BASEDIR_VERSION or - MY_BASEDIR if defined, else append "/my/running". - own_path_name_part is concatinated to result. - my_path puts result in to and returns to */ - -char * my_path(char * to, const char *progname, - const char *own_pathname_part) -{ - char *start, *end, *prog; - size_t to_length; - DBUG_ENTER("my_path"); - - start=to; /* Return this */ - if (progname && (dirname_part(to, progname, &to_length) || - find_file_in_path(to,progname) || - ((prog=getenv("_")) != 0 && - dirname_part(to, prog, &to_length)))) - { - (void) intern_filename(to,to); - if (!test_if_hard_path(to)) - { - if (!my_getwd(curr_dir,FN_REFLEN,MYF(0))) - bchange((uchar*) to, 0, (uchar*) curr_dir, strlen(curr_dir), strlen(to)+1); - } - } - else - { - if ((end = getenv("MY_BASEDIR_VERSION")) == 0 && - (end = getenv("MY_BASEDIR")) == 0) - { -#ifdef DEFAULT_BASEDIR - end= (char*) DEFAULT_BASEDIR; -#else - end= (char*) "/my/"; -#endif - } - (void) intern_filename(to,end); - to=strend(to); - if (to != start && to[-1] != FN_LIBCHAR) - *to++ = FN_LIBCHAR; - (void) strmov(to,own_pathname_part); - } - DBUG_PRINT("exit",("to: '%s'",start)); - DBUG_RETURN(start); -} /* my_path */ - - - /* test if file without filename is found in path */ - /* Returns to if found and to has dirpart if found, else NullS */ - -#if defined(__WIN__) -#define F_OK 0 -#define PATH_SEP ';' -#define PROGRAM_EXTENSION ".exe" -#else -#define PATH_SEP ':' -#endif - -static char *find_file_in_path(char *to, const char *name) -{ - char *path,*pos,dir[2]; - const char *ext=""; - - if (!(path=getenv("PATH"))) - return NullS; - dir[0]=FN_LIBCHAR; dir[1]=0; -#ifdef PROGRAM_EXTENSION - if (!fn_ext(name)[0]) - ext=PROGRAM_EXTENSION; -#endif - - for (pos=path ; (pos=strchr(pos,PATH_SEP)) ; path= ++pos) - { - if (path != pos) - { - strxmov(strnmov(to,path,(uint) (pos-path)),dir,name,ext,NullS); - if (!access(to,F_OK)) - { - to[(uint) (pos-path)+1]=0; /* Return path only */ - return to; - } - } - } -#ifdef __WIN__ - to[0]=FN_CURLIB; - strxmov(to+1,dir,name,ext,NullS); - if (!access(to,F_OK)) /* Test in current dir */ - { - to[2]=0; /* Leave ".\" */ - return to; - } -#endif - return NullS; /* File not found */ -} diff --git a/dep/mysqllite/mysys/mf_qsort.c b/dep/mysqllite/mysys/mf_qsort.c deleted file mode 100644 index 4b3ecb603a6..00000000000 --- a/dep/mysqllite/mysys/mf_qsort.c +++ /dev/null @@ -1,216 +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 */ - -/* - qsort implementation optimized for comparison of pointers - Inspired by the qsort implementations by Douglas C. Schmidt, - and Bentley & McIlroy's "Engineering a Sort Function". -*/ - - -#include "mysys_priv.h" -#ifndef SCO -#include <m_string.h> -#endif - -/* We need to use qsort with 2 different compare functions */ -#ifdef QSORT_EXTRA_CMP_ARGUMENT -#define CMP(A,B) ((*cmp)(cmp_argument,(A),(B))) -#else -#define CMP(A,B) ((*cmp)((A),(B))) -#endif - -#define SWAP(A, B, size,swap_ptrs) \ -do { \ - if (swap_ptrs) \ - { \ - reg1 char **a = (char**) (A), **b = (char**) (B); \ - char *tmp = *a; *a++ = *b; *b++ = tmp; \ - } \ - else \ - { \ - reg1 char *a = (A), *b = (B); \ - reg3 char *end= a+size; \ - do \ - { \ - char tmp = *a; *a++ = *b; *b++ = tmp; \ - } while (a < end); \ - } \ -} while (0) - -/* Put the median in the middle argument */ -#define MEDIAN(low, mid, high) \ -{ \ - if (CMP(high,low) < 0) \ - SWAP(high, low, size, ptr_cmp); \ - if (CMP(mid, low) < 0) \ - SWAP(mid, low, size, ptr_cmp); \ - else if (CMP(high, mid) < 0) \ - SWAP(mid, high, size, ptr_cmp); \ -} - -/* The following node is used to store ranges to avoid recursive calls */ - -typedef struct st_stack -{ - char *low,*high; -} stack_node; - -#define PUSH(LOW,HIGH) {stack_ptr->low = LOW; stack_ptr++->high = HIGH;} -#define POP(LOW,HIGH) {LOW = (--stack_ptr)->low; HIGH = stack_ptr->high;} - -/* The following stack size is enough for ulong ~0 elements */ -#define STACK_SIZE (8 * sizeof(unsigned long int)) -#define THRESHOLD_FOR_INSERT_SORT 10 -#if defined(QSORT_TYPE_IS_VOID) -#define SORT_RETURN return -#else -#define SORT_RETURN return 0 -#endif - -/**************************************************************************** -** 'standard' quicksort with the following extensions: -** -** Can be compiled with the qsort2_cmp compare function -** Store ranges on stack to avoid recursion -** Use insert sort on small ranges -** Optimize for sorting of pointers (used often by MySQL) -** Use median comparison to find partition element -*****************************************************************************/ - -#ifdef QSORT_EXTRA_CMP_ARGUMENT -qsort_t my_qsort2(void *base_ptr, size_t count, size_t size, qsort2_cmp cmp, - void *cmp_argument) -#else -qsort_t my_qsort(void *base_ptr, size_t count, size_t size, qsort_cmp cmp) -#endif -{ - char *low, *high, *pivot; - stack_node stack[STACK_SIZE], *stack_ptr; - my_bool ptr_cmp; - /* Handle the simple case first */ - /* This will also make the rest of the code simpler */ - if (count <= 1) - SORT_RETURN; - - low = (char*) base_ptr; - high = low+ size * (count - 1); - stack_ptr = stack + 1; -#ifdef HAVE_purify - /* The first element in the stack will be accessed for the last POP */ - stack[0].low=stack[0].high=0; -#endif - pivot = (char *) my_alloca((int) size); - ptr_cmp= size == sizeof(char*) && !((low - (char*) 0)& (sizeof(char*)-1)); - - /* The following loop sorts elements between high and low */ - do - { - char *low_ptr, *high_ptr, *mid; - - count=((size_t) (high - low) / size)+1; - /* If count is small, then an insert sort is faster than qsort */ - if (count < THRESHOLD_FOR_INSERT_SORT) - { - for (low_ptr = low + size; low_ptr <= high; low_ptr += size) - { - char *ptr; - for (ptr = low_ptr; ptr > low && CMP(ptr - size, ptr) > 0; - ptr -= size) - SWAP(ptr, ptr - size, size, ptr_cmp); - } - POP(low, high); - continue; - } - - /* Try to find a good middle element */ - mid= low + size * (count >> 1); - if (count > 40) /* Must be bigger than 24 */ - { - size_t step = size* (count / 8); - MEDIAN(low, low + step, low+step*2); - MEDIAN(mid - step, mid, mid+step); - MEDIAN(high - 2 * step, high-step, high); - /* Put best median in 'mid' */ - MEDIAN(low+step, mid, high-step); - low_ptr = low; - high_ptr = high; - } - else - { - MEDIAN(low, mid, high); - /* The low and high argument are already in sorted against 'pivot' */ - low_ptr = low + size; - high_ptr = high - size; - } - memcpy(pivot, mid, size); - - do - { - while (CMP(low_ptr, pivot) < 0) - low_ptr += size; - while (CMP(pivot, high_ptr) < 0) - high_ptr -= size; - - if (low_ptr < high_ptr) - { - SWAP(low_ptr, high_ptr, size, ptr_cmp); - low_ptr += size; - high_ptr -= size; - } - else - { - if (low_ptr == high_ptr) - { - low_ptr += size; - high_ptr -= size; - } - break; - } - } - while (low_ptr <= high_ptr); - - /* - Prepare for next iteration. - Skip partitions of size 1 as these doesn't have to be sorted - Push the larger partition and sort the smaller one first. - This ensures that the stack is keept small. - */ - - if ((int) (high_ptr - low) <= 0) - { - if ((int) (high - low_ptr) <= 0) - { - POP(low, high); /* Nothing more to sort */ - } - else - low = low_ptr; /* Ignore small left part. */ - } - else if ((int) (high - low_ptr) <= 0) - high = high_ptr; /* Ignore small right part. */ - else if ((high_ptr - low) > (high - low_ptr)) - { - PUSH(low, high_ptr); /* Push larger left part */ - low = low_ptr; - } - else - { - PUSH(low_ptr, high); /* Push larger right part */ - high = high_ptr; - } - } while (stack_ptr > stack); - my_afree(pivot); - SORT_RETURN; -} diff --git a/dep/mysqllite/mysys/mf_qsort2.c b/dep/mysqllite/mysys/mf_qsort2.c deleted file mode 100644 index ca2bd1a4952..00000000000 --- a/dep/mysqllite/mysys/mf_qsort2.c +++ /dev/null @@ -1,19 +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 */ - -/* qsort that sends one extra argument to the compare subrutine */ - -#define QSORT_EXTRA_CMP_ARGUMENT -#include "mf_qsort.c" diff --git a/dep/mysqllite/mysys/mf_radix.c b/dep/mysqllite/mysys/mf_radix.c deleted file mode 100644 index 582ca76b8f8..00000000000 --- a/dep/mysqllite/mysys/mf_radix.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 */ - -/* - Radixsort for pointers to fixed length strings. - A very quick sort for not to long (< 20 char) strings. - Neads a extra buffers of number_of_elements pointers but is - 2-3 times faster than quicksort -*/ - -#include "mysys_priv.h" -#include <m_string.h> - - /* Radixsort */ - -void radixsort_for_str_ptr(uchar **base, uint number_of_elements, size_t size_of_element, uchar **buffer) -{ - uchar **end,**ptr,**buffer_ptr; - uint32 *count_ptr,*count_end,count[256]; - int pass; - - end=base+number_of_elements; count_end=count+256; - for (pass=(int) size_of_element-1 ; pass >= 0 ; pass--) - { - bzero((uchar*) count,sizeof(uint32)*256); - for (ptr= base ; ptr < end ; ptr++) - count[ptr[0][pass]]++; - if (count[0] == number_of_elements) - goto next; - for (count_ptr=count+1 ; count_ptr < count_end ; count_ptr++) - { - if (*count_ptr == number_of_elements) - goto next; - (*count_ptr)+= *(count_ptr-1); - } - for (ptr= end ; ptr-- != base ;) - buffer[--count[ptr[0][pass]]]= *ptr; - for (ptr=base, buffer_ptr=buffer ; ptr < end ;) - (*ptr++) = *buffer_ptr++; - next:; - } -} diff --git a/dep/mysqllite/mysys/mf_same.c b/dep/mysqllite/mysys/mf_same.c deleted file mode 100644 index 6738dc8051e..00000000000 --- a/dep/mysqllite/mysys/mf_same.c +++ /dev/null @@ -1,40 +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 */ - -/* Kopierar biblioteksstrukturen och extensionen fr}n ett filnamn */ - -#include "mysys_priv.h" -#include <m_string.h> - - /* - Copy directory and/or extension between filenames. - (For the meaning of 'flag', check mf_format.c) - 'to' may be equal to 'name'. - Returns 'to'. - */ - -char * fn_same(char *to, const char *name, int flag) -{ - char dev[FN_REFLEN]; - const char *ext; - size_t dev_length; - DBUG_ENTER("fn_same"); - DBUG_PRINT("enter",("to: %s name: %s flag: %d",to,name,flag)); - - if ((ext=strrchr(name+dirname_part(dev, name, &dev_length),FN_EXTCHAR)) == 0) - ext=""; - - DBUG_RETURN(fn_format(to,to,dev,ext,flag)); -} /* fn_same */ diff --git a/dep/mysqllite/mysys/mf_sort.c b/dep/mysqllite/mysys/mf_sort.c deleted file mode 100644 index a3e7465ead0..00000000000 --- a/dep/mysqllite/mysys/mf_sort.c +++ /dev/null @@ -1,41 +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 */ - -/* Sort of string pointers in string-order with radix or qsort */ - -#include "mysys_priv.h" -#include <m_string.h> - -void my_string_ptr_sort(uchar *base, uint items, size_t size) -{ -#if INT_MAX > 65536L - uchar **ptr=0; - - if (size <= 20 && items >= 1000 && items < 100000 && - (ptr= (uchar**) my_malloc(items*sizeof(char*),MYF(0)))) - { - radixsort_for_str_ptr((uchar**) base,items,size,ptr); - my_free(ptr); - } - else -#endif - { - if (size && items) - { - my_qsort2(base,items, sizeof(uchar*), get_ptr_compare(size), - (void*) &size); - } - } -} diff --git a/dep/mysqllite/mysys/mf_soundex.c b/dep/mysqllite/mysys/mf_soundex.c deleted file mode 100644 index fe30d8c81af..00000000000 --- a/dep/mysqllite/mysys/mf_soundex.c +++ /dev/null @@ -1,105 +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 */ - -/**************************************************************** -* SOUNDEX ALGORITHM in C * -* * -* The basic Algorithm source is taken from EDN Nov. * -* 14, 1985 pg. 36. * -* * -* As a test Those in Illinois will find that the * -* first group of numbers in their drivers license * -* number is the soundex number for their last name. * -* * -* RHW PC-IBBS ID. #1230 * -* * -* As an extension if remove_garbage is set then all non- * -* alpha characters are skipped * -* * -* Note, that this implementation corresponds to the * -* original version of the algorithm, not to the more * -* popular "enhanced" version, described by Knuth. * -****************************************************************/ - -#include "mysys_priv.h" -#include <m_ctype.h> -#include "my_static.h" - -static char get_scode(CHARSET_INFO * cs, char **ptr,pbool remove_garbage); - - /* outputed string is 4 byte long */ - /* out_pntr can be == in_pntr */ - -void soundex(CHARSET_INFO * cs,register char * out_pntr, char * in_pntr, - pbool remove_garbage) -{ - char ch,last_ch; - reg3 char * end; - register uchar *map=cs->to_upper; - - if (remove_garbage) - { - while (*in_pntr && !my_isalpha(cs,*in_pntr)) /* Skip pre-space */ - in_pntr++; - } - *out_pntr++ = map[(uchar)*in_pntr]; /* Copy first letter */ - last_ch = get_scode(cs,&in_pntr,0); /* code of the first letter */ - /* for the first 'double-letter */ - /* check. */ - end=out_pntr+3; /* Loop on input letters until */ - /* end of input (null) or output */ - /* letter code count = 3 */ - - in_pntr++; - while (out_pntr < end && (ch = get_scode(cs,&in_pntr,remove_garbage)) != 0) - { - in_pntr++; - if ((ch != '0') && (ch != last_ch)) /* if not skipped or double */ - { - *out_pntr++ = ch; /* letter, copy to output */ - } /* for next double-letter check */ - last_ch = ch; /* save code of last input letter */ - } - while (out_pntr < end) - *out_pntr++ = '0'; - *out_pntr=0; /* end string */ - return; -} /* soundex */ - - - /* - If alpha, map input letter to soundex code. - If not alpha and remove_garbage is set then skip to next char - else return 0 - */ - -static char get_scode(CHARSET_INFO * cs,char **ptr, pbool remove_garbage) -{ - uchar ch; - - if (remove_garbage) - { - while (**ptr && !my_isalpha(cs,**ptr)) - (*ptr)++; - } - ch=my_toupper(cs,**ptr); - if (ch < 'A' || ch > 'Z') - { - if (my_isalpha(cs,ch)) /* If extended alfa (country spec) */ - return '0'; /* threat as vokal */ - return 0; /* Can't map */ - } - return(soundex_map[ch-'A']); -} /* get_scode */ diff --git a/dep/mysqllite/mysys/mf_tempdir.c b/dep/mysqllite/mysys/mf_tempdir.c deleted file mode 100644 index c84987cfc96..00000000000 --- a/dep/mysqllite/mysys/mf_tempdir.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 <m_string.h> - -#if defined(__WIN__) -#define DELIM ';' -#else -#define DELIM ':' -#endif - -my_bool init_tmpdir(MY_TMPDIR *tmpdir, const char *pathlist) -{ - char *end, *copy; - char buff[FN_REFLEN]; - DBUG_ENTER("init_tmpdir"); - DBUG_PRINT("enter", ("pathlist: %s", pathlist ? pathlist : "NULL")); - - mysql_mutex_init(key_TMPDIR_mutex, &tmpdir->mutex, MY_MUTEX_INIT_FAST); - if (my_init_dynamic_array(&tmpdir->full_list, sizeof(char*), 1, 5)) - goto err; - if (!pathlist || !pathlist[0]) - { - /* Get default temporary directory */ - pathlist=getenv("TMPDIR"); /* Use this if possible */ -#if defined(__WIN__) - if (!pathlist) - pathlist=getenv("TEMP"); - if (!pathlist) - pathlist=getenv("TMP"); -#endif - if (!pathlist || !pathlist[0]) - pathlist=(char*) P_tmpdir; - } - do - { - size_t length; - end=strcend(pathlist, DELIM); - strmake(buff, pathlist, (uint) (end-pathlist)); - length= cleanup_dirname(buff, buff); - if (!(copy= my_strndup(buff, length, MYF(MY_WME))) || - insert_dynamic(&tmpdir->full_list, (uchar*) ©)) - DBUG_RETURN(TRUE); - pathlist=end+1; - } - while (*end); - freeze_size(&tmpdir->full_list); - tmpdir->list=(char **)tmpdir->full_list.buffer; - tmpdir->max=tmpdir->full_list.elements-1; - tmpdir->cur=0; - DBUG_RETURN(FALSE); - -err: - delete_dynamic(&tmpdir->full_list); /* Safe to free */ - mysql_mutex_destroy(&tmpdir->mutex); - DBUG_RETURN(TRUE); -} - - -char *my_tmpdir(MY_TMPDIR *tmpdir) -{ - char *dir; - if (!tmpdir->max) - return tmpdir->list[0]; - mysql_mutex_lock(&tmpdir->mutex); - dir=tmpdir->list[tmpdir->cur]; - tmpdir->cur= (tmpdir->cur == tmpdir->max) ? 0 : tmpdir->cur+1; - mysql_mutex_unlock(&tmpdir->mutex); - return dir; -} - -void free_tmpdir(MY_TMPDIR *tmpdir) -{ - uint i; - if (!tmpdir->full_list.elements) - return; - for (i=0; i<=tmpdir->max; i++) - my_free(tmpdir->list[i]); - delete_dynamic(&tmpdir->full_list); - mysql_mutex_destroy(&tmpdir->mutex); -} - diff --git a/dep/mysqllite/mysys/mf_tempfile.c b/dep/mysqllite/mysys/mf_tempfile.c deleted file mode 100644 index e85124fb4c3..00000000000 --- a/dep/mysqllite/mysys/mf_tempfile.c +++ /dev/null @@ -1,177 +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 <m_string.h> -#include "my_static.h" -#include "mysys_err.h" -#include <errno.h> -#ifdef HAVE_PATHS_H -#include <paths.h> -#endif - - - -/* - @brief - Create a temporary file with unique name in a given directory - - @details - create_temp_file - to pointer to buffer where temporary filename will be stored - dir directory where to create the file - prefix prefix the filename with this - mode Flags to use for my_create/my_open - MyFlags Magic flags - - @return - File descriptor of opened file if success - -1 and sets errno if fails. - - @note - The behaviour of this function differs a lot between - implementation, it's main use is to generate a file with - a name that does not already exist. - - When passing O_TEMPORARY flag in "mode" the file should - be automatically deleted - - The implementation using mkstemp should be considered the - reference implementation when adding a new or modifying an - existing one - -*/ - -File create_temp_file(char *to, const char *dir, const char *prefix, - int mode __attribute__((unused)), - myf MyFlags __attribute__((unused))) -{ - File file= -1; -#ifdef __WIN__ - TCHAR path_buf[MAX_PATH-14]; -#endif - - DBUG_ENTER("create_temp_file"); - DBUG_PRINT("enter", ("dir: %s, prefix: %s", dir, prefix)); -#if defined (__WIN__) - - /* - Use GetTempPath to determine path for temporary files. - This is because the documentation for GetTempFileName - has the following to say about this parameter: - "If this parameter is NULL, the function fails." - */ - if (!dir) - { - if(GetTempPath(sizeof(path_buf), path_buf) > 0) - dir = path_buf; - } - /* - Use GetTempFileName to generate a unique filename, create - the file and release it's handle - - uses up to the first three letters from prefix - */ - if (GetTempFileName(dir, prefix, 0, to) == 0) - DBUG_RETURN(-1); - - DBUG_PRINT("info", ("name: %s", to)); - - /* - Open the file without the "open only if file doesn't already exist" - since the file has already been created by GetTempFileName - */ - if ((file= my_open(to, (mode & ~O_EXCL), MyFlags)) < 0) - { - /* Open failed, remove the file created by GetTempFileName */ - int tmp= my_errno; - (void) my_delete(to, MYF(0)); - my_errno= tmp; - } - -#elif defined(HAVE_MKSTEMP) - { - char prefix_buff[30]; - uint pfx_len; - File org_file; - - pfx_len= (uint) (strmov(strnmov(prefix_buff, - prefix ? prefix : "tmp.", - sizeof(prefix_buff)-7),"XXXXXX") - - prefix_buff); - if (!dir && ! (dir =getenv("TMPDIR"))) - dir=P_tmpdir; - if (strlen(dir)+ pfx_len > FN_REFLEN-2) - { - errno=my_errno= ENAMETOOLONG; - DBUG_RETURN(file); - } - strmov(convert_dirname(to,dir,NullS),prefix_buff); - org_file=mkstemp(to); - if (mode & O_TEMPORARY) - (void) my_delete(to, MYF(MY_WME | ME_NOINPUT)); - file=my_register_filename(org_file, to, FILE_BY_MKSTEMP, - EE_CANTCREATEFILE, MyFlags); - /* If we didn't manage to register the name, remove the temp file */ - if (org_file >= 0 && file < 0) - { - int tmp=my_errno; - close(org_file); - (void) my_delete(to, MYF(MY_WME | ME_NOINPUT)); - my_errno=tmp; - } - } -#elif defined(HAVE_TEMPNAM) - { - extern char **environ; - - char *res,**old_env,*temp_env[1]; - if (dir && !dir[0]) - { /* Change empty string to current dir */ - to[0]= FN_CURLIB; - to[1]= 0; - dir=to; - } - - old_env= (char**) environ; - if (dir) - { /* Don't use TMPDIR if dir is given */ - environ=(const char**) temp_env; - temp_env[0]=0; - } - - if ((res=tempnam((char*) dir, (char*) prefix))) - { - strmake(to,res,FN_REFLEN-1); - (*free)(res); - file=my_create(to,0, - (int) (O_RDWR | O_BINARY | O_TRUNC | O_EXCL | O_NOFOLLOW | - O_TEMPORARY | O_SHORT_LIVED), - MYF(MY_WME)); - - } - else - { - DBUG_PRINT("error",("Got error: %d from tempnam",errno)); - } - - environ=(const char**) old_env; - } -#else -#error No implementation found for create_temp_file -#endif - if (file >= 0) - thread_safe_increment(my_tmp_file_created,&THR_LOCK_open); - DBUG_RETURN(file); -} diff --git a/dep/mysqllite/mysys/mf_unixpath.c b/dep/mysqllite/mysys/mf_unixpath.c deleted file mode 100644 index ee81aae4584..00000000000 --- a/dep/mysqllite/mysys/mf_unixpath.c +++ /dev/null @@ -1,36 +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 <m_string.h> - -/** - Convert filename to unix style filename. - - @remark On Windows, converts '\' to '/'. - - @param to A pathname. -*/ - -void to_unix_path(char *to __attribute__((unused))) -{ -#if FN_LIBCHAR != '/' - { - to--; - while ((to=strchr(to+1,FN_LIBCHAR)) != 0) - *to='/'; - } -#endif -} diff --git a/dep/mysqllite/mysys/mf_wcomp.c b/dep/mysqllite/mysys/mf_wcomp.c deleted file mode 100644 index 4786537d1a5..00000000000 --- a/dep/mysqllite/mysys/mf_wcomp.c +++ /dev/null @@ -1,89 +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 */ - -/* Funktions for comparing with wild-cards */ - -#include "mysys_priv.h" - - /* Test if a string is "comparable" to a wild-card string */ - /* returns 0 if the strings are "comparable" */ - -char wild_many='*'; -char wild_one='?'; -char wild_prefix=0; /* QQ this can potentially cause a SIGSEGV */ - -int wild_compare(register const char *str, register const char *wildstr, - pbool str_is_pattern) -{ - char cmp; - DBUG_ENTER("wild_compare"); - - while (*wildstr) - { - while (*wildstr && *wildstr != wild_many && *wildstr != wild_one) - { - if (*wildstr == wild_prefix && wildstr[1]) - { - wildstr++; - if (str_is_pattern && *str++ != wild_prefix) - DBUG_RETURN(1); - } - if (*wildstr++ != *str++) - DBUG_RETURN(1); - } - if (! *wildstr ) - DBUG_RETURN(*str != 0); - if (*wildstr++ == wild_one) - { - if (! *str || (str_is_pattern && *str == wild_many)) - DBUG_RETURN(1); /* One char; skip */ - if (*str++ == wild_prefix && str_is_pattern && *str) - str++; - } - else - { /* Found '*' */ - while (str_is_pattern && *str == wild_many) - str++; - for (; *wildstr == wild_many || *wildstr == wild_one; wildstr++) - if (*wildstr == wild_many) - { - while (str_is_pattern && *str == wild_many) - str++; - } - else - { - if (str_is_pattern && *str == wild_prefix && str[1]) - str+=2; - else if (! *str++) - DBUG_RETURN (1); - } - if (!*wildstr) - DBUG_RETURN(0); /* '*' as last char: OK */ - if ((cmp= *wildstr) == wild_prefix && wildstr[1] && !str_is_pattern) - cmp=wildstr[1]; - for (;;str++) - { - while (*str && *str != cmp) - str++; - if (!*str) - DBUG_RETURN (1); - if (wild_compare(str,wildstr,str_is_pattern) == 0) - DBUG_RETURN (0); - } - /* We will never come here */ - } - } - DBUG_RETURN (*str != 0); -} /* wild_compare */ diff --git a/dep/mysqllite/mysys/mulalloc.c b/dep/mysqllite/mysys/mulalloc.c deleted file mode 100644 index f4ca3d9f9ab..00000000000 --- a/dep/mysqllite/mysys/mulalloc.c +++ /dev/null @@ -1,63 +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 <stdarg.h> - -/* - Malloc many pointers at the same time - Only ptr1 can be free'd, and doing this will free all - the memory allocated. ptr2, etc all point inside big allocated - memory area. - - SYNOPSIS - my_multi_malloc() - myFlags Flags - ptr1, length1 Multiple arguments terminated by null ptr - ptr2, length2 ... - ... - NULL -*/ - -void* my_multi_malloc(myf myFlags, ...) -{ - va_list args; - char **ptr,*start,*res; - size_t tot_length,length; - DBUG_ENTER("my_multi_malloc"); - - va_start(args,myFlags); - tot_length=0; - while ((ptr=va_arg(args, char **))) - { - length=va_arg(args,uint); - tot_length+=ALIGN_SIZE(length); - } - va_end(args); - - if (!(start=(char *) my_malloc(tot_length,myFlags))) - DBUG_RETURN(0); /* purecov: inspected */ - - va_start(args,myFlags); - res=start; - while ((ptr=va_arg(args, char **))) - { - *ptr=res; - length=va_arg(args,uint); - res+=ALIGN_SIZE(length); - } - va_end(args); - DBUG_RETURN((void*) start); -} diff --git a/dep/mysqllite/mysys/my_access.c b/dep/mysqllite/mysys/my_access.c deleted file mode 100644 index 210946d50a8..00000000000 --- a/dep/mysqllite/mysys/my_access.c +++ /dev/null @@ -1,201 +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 <m_string.h> - -#ifdef __WIN__ - -/* - Check a file or path for accessability. - - SYNOPSIS - file_access() - path Path to file - amode Access method - - DESCRIPTION - This function wraps the normal access method because the access - available in MSVCRT> +reports that filenames such as LPT1 and - COM1 are valid (they are but should not be so for us). - - RETURN VALUES - 0 ok - -1 error (We use -1 as my_access is mapped to access on other platforms) -*/ - -int my_access(const char *path, int amode) -{ - WIN32_FILE_ATTRIBUTE_DATA fileinfo; - BOOL result; - - result= GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo); - if (! result || - (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & W_OK)) - { - my_errno= errno= EACCES; - return -1; - } - return 0; -} - -#endif /* __WIN__ */ - - -/* - 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[]= -{ - "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 - - SYNOPSIS - check_if_legal_filename - path Path to file - - RETURN - 0 ok - 1 reserved file name -*/ - -int check_if_legal_filename(const char *path) -{ - const char *end; - const char **reserved_name; - DBUG_ENTER("check_if_legal_filename"); - - path+= dirname_length(path); /* To start of filename */ - if (!(end= strchr(path, FN_EXTCHAR))) - end= strend(path); - if (path == end || (uint) (end - path) > MAX_RESERVED_NAME_LENGTH) - DBUG_RETURN(0); /* Simplify inner loop */ - - for (reserved_name= reserved_names; *reserved_name; reserved_name++) - { - const char *reserved= *reserved_name; /* never empty */ - const char *name= path; - - do - { - if (*reserved != my_toupper(&my_charset_latin1, *name)) - break; - if (++name == end && !reserved[1]) - DBUG_RETURN(1); /* Found wrong path */ - } while (*++reserved); - } - DBUG_RETURN(0); -} - -#endif /* defined(__WIN__) || defined(__EMX__) */ diff --git a/dep/mysqllite/mysys/my_aes.c b/dep/mysqllite/mysys/my_aes.c deleted file mode 100644 index 575d4702dee..00000000000 --- a/dep/mysqllite/mysys/my_aes.c +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (C) 2002 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 AES Encryption for MySQL - Initial version by Peter Zaitsev June 2002 -*/ - - -#include <my_global.h> -#include <m_string.h> -#include "my_aes.h" - -enum encrypt_dir { AES_ENCRYPT, AES_DECRYPT }; - -#define AES_BLOCK_SIZE 16 /* Block size in bytes */ - -#define AES_BAD_DATA -1 /* If bad data discovered during decoding */ - - -/* The structure for key information */ -typedef struct { - int nr; /* Number of rounds */ - uint32 rk[4*(AES_MAXNR + 1)]; /* key schedule */ -} KEYINSTANCE; - - -/* - This is internal function just keeps joint code of Key generation - - SYNOPSIS - my_aes_create_key() - aes_key Address of Key Instance to be created - direction Direction (are we encoding or decoding) - key Key to use for real key creation - key_length Length of the key - - DESCRIPTION - - RESULT - 0 ok - -1 Error Note: The current impementation never returns this -*/ - -static int my_aes_create_key(KEYINSTANCE *aes_key, - enum encrypt_dir direction, const char *key, - int key_length) -{ - uint8 rkey[AES_KEY_LENGTH/8]; /* The real key to be used for encryption */ - uint8 *rkey_end=rkey+AES_KEY_LENGTH/8; /* Real key boundary */ - uint8 *ptr; /* Start of the real key*/ - const char *sptr; /* Start of the working key */ - const char *key_end=key+key_length; /* Working key boundary*/ - - bzero((char*) rkey,AES_KEY_LENGTH/8); /* Set initial key */ - - for (ptr= rkey, sptr= key; sptr < key_end; ptr++,sptr++) - { - if (ptr == rkey_end) - ptr= rkey; /* Just loop over tmp_key until we used all key */ - *ptr^= (uint8) *sptr; - } -#ifdef AES_USE_KEY_BITS - /* - This block is intended to allow more weak encryption if application - build with libmysqld needs to correspond to export regulations - It should be never used in normal distribution as does not give - any speed improvement. - To get worse security define AES_USE_KEY_BITS to number of bits - you want key to be. It should be divisible by 8 - - WARNING: Changing this value results in changing of enryption for - all key lengths so altering this value will result in impossibility - to decrypt data encrypted with previous value - */ -#define AES_USE_KEY_BYTES (AES_USE_KEY_BITS/8) - /* - To get weaker key we use first AES_USE_KEY_BYTES bytes of created key - and cyclically copy them until we created all required key length - */ - for (ptr= rkey+AES_USE_KEY_BYTES, sptr=rkey ; ptr < rkey_end; - ptr++,sptr++) - { - if (sptr == rkey+AES_USE_KEY_BYTES) - sptr=rkey; - *ptr=*sptr; - } -#endif - if (direction == AES_DECRYPT) - aes_key->nr = rijndaelKeySetupDec(aes_key->rk, rkey, AES_KEY_LENGTH); - else - aes_key->nr = rijndaelKeySetupEnc(aes_key->rk, rkey, AES_KEY_LENGTH); - return 0; -} - - -/* - Crypt buffer with AES encryption algorithm. - - SYNOPSIS - my_aes_encrypt() - source Pointer to data for encryption - source_length Size of encryption data - dest Buffer to place encrypted data (must be large enough) - key Key to be used for encryption - key_length Length of the key. Will handle keys of any length - - RETURN - >= 0 Size of encrypted data - < 0 Error -*/ - -int my_aes_encrypt(const char* source, int source_length, char* dest, - const char* key, int key_length) -{ - KEYINSTANCE aes_key; - uint8 block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */ - int rc; /* result codes */ - int num_blocks; /* number of complete blocks */ - char pad_len; /* pad size for the last block */ - int i; - - if ((rc= my_aes_create_key(&aes_key,AES_ENCRYPT,key,key_length))) - return rc; - - num_blocks = source_length/AES_BLOCK_SIZE; - - for (i = num_blocks; i > 0; i--) /* Encode complete blocks */ - { - rijndaelEncrypt(aes_key.rk, aes_key.nr, (const uint8*) source, - (uint8*) dest); - source+= AES_BLOCK_SIZE; - dest+= AES_BLOCK_SIZE; - } - - /* Encode the rest. We always have incomplete block */ - pad_len = AES_BLOCK_SIZE - (source_length - AES_BLOCK_SIZE*num_blocks); - memcpy(block, source, 16 - pad_len); - bfill(block + AES_BLOCK_SIZE - pad_len, pad_len, pad_len); - rijndaelEncrypt(aes_key.rk, aes_key.nr, block, (uint8*) dest); - return AES_BLOCK_SIZE*(num_blocks + 1); -} - - -/* - DeCrypt buffer with AES encryption algorithm. - - SYNOPSIS - my_aes_decrypt() - source Pointer to data for decryption - source_length Size of encrypted data - dest Buffer to place decrypted data (must be large enough) - key Key to be used for decryption - key_length Length of the key. Will handle keys of any length - - RETURN - >= 0 Size of encrypted data - < 0 Error -*/ - -int my_aes_decrypt(const char *source, int source_length, char *dest, - const char *key, int key_length) -{ - KEYINSTANCE aes_key; - uint8 block[AES_BLOCK_SIZE]; /* 128 bit block used for padding */ - int rc; /* Result codes */ - int num_blocks; /* Number of complete blocks */ - uint pad_len; /* Pad size for the last block */ - int i; - - if ((rc=my_aes_create_key(&aes_key,AES_DECRYPT,key,key_length))) - return rc; - - num_blocks = source_length/AES_BLOCK_SIZE; - - if ((source_length != num_blocks*AES_BLOCK_SIZE) || num_blocks ==0 ) - return AES_BAD_DATA; /* Input size has to be even and at least one block */ - - for (i = num_blocks-1; i > 0; i--) /* Decode all but last blocks */ - { - rijndaelDecrypt(aes_key.rk, aes_key.nr, (const uint8*) source, - (uint8*) dest); - source+= AES_BLOCK_SIZE; - dest+= AES_BLOCK_SIZE; - } - - rijndaelDecrypt(aes_key.rk, aes_key.nr, (const uint8*) source, block); - /* Use last char in the block as size */ - pad_len = (uint) (uchar) block[AES_BLOCK_SIZE-1]; - - if (pad_len > AES_BLOCK_SIZE) - return AES_BAD_DATA; - /* We could also check whole padding but we do not really need this */ - - memcpy(dest, block, AES_BLOCK_SIZE - pad_len); - return AES_BLOCK_SIZE*num_blocks - pad_len; -} - - -/* - Get size of buffer which will be large enough for encrypted data - - SYNOPSIS - my_aes_get_size() - source_length Length of data to be encrypted - - RETURN - Size of buffer required to store encrypted data -*/ - -int my_aes_get_size(int source_length) -{ - return AES_BLOCK_SIZE*(source_length/AES_BLOCK_SIZE)+AES_BLOCK_SIZE; -} diff --git a/dep/mysqllite/mysys/my_alarm.c b/dep/mysqllite/mysys/my_alarm.c deleted file mode 100644 index d6a0da1bd13..00000000000 --- a/dep/mysqllite/mysys/my_alarm.c +++ /dev/null @@ -1,32 +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 */ - -/* Function to set a varible when we got a alarm */ -/* Used by my_lock samt functions in m_alarm.h */ - - -#include "mysys_priv.h" -#include "my_alarm.h" - -#ifdef HAVE_ALARM - - /* ARGSUSED */ -sig_handler my_set_alarm_variable(int signo __attribute__((unused))) -{ - my_have_got_alarm=1; /* Tell program that time expired */ - return; -} - -#endif /* HAVE_ALARM */ diff --git a/dep/mysqllite/mysys/my_alloc.c b/dep/mysqllite/mysys/my_alloc.c deleted file mode 100644 index 903826dd975..00000000000 --- a/dep/mysqllite/mysys/my_alloc.c +++ /dev/null @@ -1,436 +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 */ - -/* Routines to handle mallocing of results which will be freed the same time */ - -#include <my_global.h> -#include <my_sys.h> -#include <m_string.h> -#undef EXTRA_DEBUG -#define EXTRA_DEBUG - - -/* - Initialize memory root - - SYNOPSIS - init_alloc_root() - mem_root - memory root to initialize - block_size - size of chunks (blocks) used for memory allocation - (It is external size of chunk i.e. it should include - memory required for internal structures, thus it - should be no less than ALLOC_ROOT_MIN_BLOCK_SIZE) - pre_alloc_size - if non-0, then size of block that should be - pre-allocated during memory root initialization. - - DESCRIPTION - This function prepares memory root for further use, sets initial size of - chunk for memory allocation and pre-allocates first block if specified. - Altough error can happen during execution of this function if - pre_alloc_size is non-0 it won't be reported. Instead it will be - reported as error in first alloc_root() on this memory root. -*/ - -void init_alloc_root(MEM_ROOT *mem_root, size_t block_size, - size_t pre_alloc_size __attribute__((unused))) -{ - DBUG_ENTER("init_alloc_root"); - DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); - - mem_root->free= mem_root->used= mem_root->pre_alloc= 0; - mem_root->min_malloc= 32; - mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE; - mem_root->error_handler= 0; - mem_root->block_num= 4; /* We shift this with >>2 */ - mem_root->first_block_usage= 0; - -#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG)) - if (pre_alloc_size) - { - if ((mem_root->free= mem_root->pre_alloc= - (USED_MEM*) my_malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)), - MYF(0)))) - { - mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM)); - mem_root->free->left= pre_alloc_size; - mem_root->free->next= 0; - } - } -#endif - DBUG_VOID_RETURN; -} - - -/* - SYNOPSIS - reset_root_defaults() - mem_root memory root to change defaults of - block_size new value of block size. Must be greater or equal - than ALLOC_ROOT_MIN_BLOCK_SIZE (this value is about - 68 bytes and depends on platform and compilation flags) - pre_alloc_size new size of preallocated block. If not zero, - must be equal to or greater than block size, - otherwise means 'no prealloc'. - DESCRIPTION - Function aligns and assigns new value to block size; then it tries to - reuse one of existing blocks as prealloc block, or malloc new one of - requested size. If no blocks can be reused, all unused blocks are freed - before allocation. -*/ - -void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, - size_t pre_alloc_size __attribute__((unused))) -{ - DBUG_ASSERT(alloc_root_inited(mem_root)); - - mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE; -#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG)) - if (pre_alloc_size) - { - size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)); - if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size) - { - USED_MEM *mem, **prev= &mem_root->free; - /* - Free unused blocks, so that consequent calls - to reset_root_defaults won't eat away memory. - */ - while (*prev) - { - mem= *prev; - if (mem->size == size) - { - /* We found a suitable block, no need to do anything else */ - mem_root->pre_alloc= mem; - return; - } - if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size) - { - /* remove block from the list and free it */ - *prev= mem->next; - my_free(mem); - } - else - prev= &mem->next; - } - /* Allocate new prealloc block and add it to the end of free list */ - if ((mem= (USED_MEM *) my_malloc(size, MYF(0)))) - { - mem->size= size; - mem->left= pre_alloc_size; - mem->next= *prev; - *prev= mem_root->pre_alloc= mem; - } - else - { - mem_root->pre_alloc= 0; - } - } - } - else -#endif - mem_root->pre_alloc= 0; -} - - -void *alloc_root(MEM_ROOT *mem_root, size_t length) -{ -#if defined(HAVE_purify) && defined(EXTRA_DEBUG) - reg1 USED_MEM *next; - DBUG_ENTER("alloc_root"); - DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); - - DBUG_ASSERT(alloc_root_inited(mem_root)); - - DBUG_EXECUTE_IF("simulate_out_of_memory", - { - if (mem_root->error_handler) - (*mem_root->error_handler)(); - DBUG_SET("-d,simulate_out_of_memory"); - DBUG_RETURN((void*) 0); /* purecov: inspected */ - }); - - length+=ALIGN_SIZE(sizeof(USED_MEM)); - if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR)))) - { - if (mem_root->error_handler) - (*mem_root->error_handler)(); - DBUG_RETURN((uchar*) 0); /* purecov: inspected */ - } - next->next= mem_root->used; - next->size= length; - mem_root->used= next; - DBUG_PRINT("exit",("ptr: 0x%lx", (long) (((char*) next)+ - ALIGN_SIZE(sizeof(USED_MEM))))); - DBUG_RETURN((uchar*) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM)))); -#else - size_t get_size, block_size; - uchar* point; - reg1 USED_MEM *next= 0; - reg2 USED_MEM **prev; - DBUG_ENTER("alloc_root"); - DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); - DBUG_ASSERT(alloc_root_inited(mem_root)); - - DBUG_EXECUTE_IF("simulate_out_of_memory", - { - /* Avoid reusing an already allocated block */ - if (mem_root->error_handler) - (*mem_root->error_handler)(); - DBUG_SET("-d,simulate_out_of_memory"); - DBUG_RETURN((void*) 0); /* purecov: inspected */ - }); - length= ALIGN_SIZE(length); - if ((*(prev= &mem_root->free)) != NULL) - { - if ((*prev)->left < length && - mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP && - (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP) - { - next= *prev; - *prev= next->next; /* Remove block from list */ - next->next= mem_root->used; - mem_root->used= next; - mem_root->first_block_usage= 0; - } - for (next= *prev ; next && next->left < length ; next= next->next) - prev= &next->next; - } - if (! next) - { /* Time to alloc new block */ - block_size= mem_root->block_size * (mem_root->block_num >> 2); - get_size= length+ALIGN_SIZE(sizeof(USED_MEM)); - get_size= max(get_size, block_size); - - if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME | ME_FATALERROR)))) - { - if (mem_root->error_handler) - (*mem_root->error_handler)(); - DBUG_RETURN((void*) 0); /* purecov: inspected */ - } - mem_root->block_num++; - next->next= *prev; - next->size= get_size; - next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); - *prev=next; - } - - point= (uchar*) ((char*) next+ (next->size-next->left)); - /*TODO: next part may be unneded due to mem_root->first_block_usage counter*/ - if ((next->left-= length) < mem_root->min_malloc) - { /* Full block */ - *prev= next->next; /* Remove block from list */ - next->next= mem_root->used; - mem_root->used= next; - mem_root->first_block_usage= 0; - } - DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point)); - DBUG_RETURN((void*) point); -#endif -} - - -/* - Allocate many pointers at the same time. - - DESCRIPTION - ptr1, ptr2, etc all point into big allocated memory area. - - SYNOPSIS - multi_alloc_root() - root Memory root - ptr1, length1 Multiple arguments terminated by a NULL pointer - ptr2, length2 ... - ... - NULL - - RETURN VALUE - A pointer to the beginning of the allocated memory block - in case of success or NULL if out of memory. -*/ - -void *multi_alloc_root(MEM_ROOT *root, ...) -{ - va_list args; - char **ptr, *start, *res; - size_t tot_length, length; - DBUG_ENTER("multi_alloc_root"); - - va_start(args, root); - tot_length= 0; - while ((ptr= va_arg(args, char **))) - { - length= va_arg(args, uint); - tot_length+= ALIGN_SIZE(length); - } - va_end(args); - - if (!(start= (char*) alloc_root(root, tot_length))) - DBUG_RETURN(0); /* purecov: inspected */ - - va_start(args, root); - res= start; - while ((ptr= va_arg(args, char **))) - { - *ptr= res; - length= va_arg(args, uint); - res+= ALIGN_SIZE(length); - } - va_end(args); - DBUG_RETURN((void*) start); -} - -#define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left) - -/* Mark all data in blocks free for reusage */ - -static inline void mark_blocks_free(MEM_ROOT* root) -{ - reg1 USED_MEM *next; - reg2 USED_MEM **last; - - /* iterate through (partially) free blocks, mark them free */ - last= &root->free; - for (next= root->free; next; next= *(last= &next->next)) - { - next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM)); - TRASH_MEM(next); - } - - /* Combine the free and the used list */ - *last= next=root->used; - - /* now go through the used blocks and mark them free */ - for (; next; next= next->next) - { - next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM)); - TRASH_MEM(next); - } - - /* Now everything is set; Indicate that nothing is used anymore */ - root->used= 0; - root->first_block_usage= 0; -} - - -/* - Deallocate everything used by alloc_root or just move - used blocks to free list if called with MY_USED_TO_FREE - - SYNOPSIS - free_root() - root Memory root - MyFlags Flags for what should be freed: - - MY_MARK_BLOCKS_FREED Don't free blocks, just mark them free - MY_KEEP_PREALLOC If this is not set, then free also the - preallocated block - - NOTES - One can call this function either with root block initialised with - init_alloc_root() or with a bzero()-ed block. - It's also safe to call this multiple times with the same mem_root. -*/ - -void free_root(MEM_ROOT *root, myf MyFlags) -{ - reg1 USED_MEM *next,*old; - DBUG_ENTER("free_root"); - DBUG_PRINT("enter",("root: 0x%lx flags: %u", (long) root, (uint) MyFlags)); - - if (MyFlags & MY_MARK_BLOCKS_FREE) - { - mark_blocks_free(root); - DBUG_VOID_RETURN; - } - if (!(MyFlags & MY_KEEP_PREALLOC)) - root->pre_alloc=0; - - for (next=root->used; next ;) - { - old=next; next= next->next ; - if (old != root->pre_alloc) - my_free(old); - } - for (next=root->free ; next ;) - { - old=next; next= next->next; - if (old != root->pre_alloc) - my_free(old); - } - root->used=root->free=0; - if (root->pre_alloc) - { - root->free=root->pre_alloc; - root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM)); - TRASH_MEM(root->pre_alloc); - root->free->next=0; - } - root->block_num= 4; - root->first_block_usage= 0; - DBUG_VOID_RETURN; -} - -/* - Find block that contains an object and set the pre_alloc to it -*/ - -void set_prealloc_root(MEM_ROOT *root, char *ptr) -{ - USED_MEM *next; - for (next=root->used; next ; next=next->next) - { - if ((char*) next <= ptr && (char*) next + next->size > ptr) - { - root->pre_alloc=next; - return; - } - } - for (next=root->free ; next ; next=next->next) - { - if ((char*) next <= ptr && (char*) next + next->size > ptr) - { - root->pre_alloc=next; - return; - } - } -} - - -char *strdup_root(MEM_ROOT *root, const char *str) -{ - return strmake_root(root, str, strlen(str)); -} - - -char *strmake_root(MEM_ROOT *root, const char *str, size_t len) -{ - char *pos; - if ((pos=alloc_root(root,len+1))) - { - memcpy(pos,str,len); - pos[len]=0; - } - return pos; -} - - -void *memdup_root(MEM_ROOT *root, const void *str, size_t len) -{ - char *pos; - if ((pos=alloc_root(root,len))) - memcpy(pos,str,len); - return pos; -} diff --git a/dep/mysqllite/mysys/my_atomic.c b/dep/mysqllite/mysys/my_atomic.c deleted file mode 100644 index 7cbe15cfb74..00000000000 --- a/dep/mysqllite/mysys/my_atomic.c +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2006 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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_sys.h> - -#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() -{ - compile_time_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 -} - -#ifdef SAFE_MUTEX -#undef pthread_mutex_init -#undef pthread_mutex_destroy -#undef pthread_mutex_lock -#undef pthread_mutex_unlock - -void plain_pthread_mutex_init(safe_mutex_t *m) -{ - pthread_mutex_init(& m->mutex, NULL); -} - -void plain_pthread_mutex_destroy(safe_mutex_t *m) -{ - pthread_mutex_destroy(& m->mutex); -} - -void plain_pthread_mutex_lock(safe_mutex_t *m) -{ - pthread_mutex_lock(& m->mutex); -} - -void plain_pthread_mutex_unlock(safe_mutex_t *m) -{ - pthread_mutex_unlock(& m->mutex); -} - -#endif - - diff --git a/dep/mysqllite/mysys/my_bit.c b/dep/mysqllite/mysys/my_bit.c deleted file mode 100644 index f072f243765..00000000000 --- a/dep/mysqllite/mysys/my_bit.c +++ /dev/null @@ -1,64 +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 <my_global.h> - -#include <my_bit.h> - -const char _my_bits_nbits[256] = { - 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, - 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, -}; - -/* - perl -e 'print map{", 0x".unpack H2,pack B8,unpack b8,chr$_}(0..255)' -*/ -const uchar _my_bits_reverse_table[256]={ -0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, -0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, -0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, -0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, -0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, -0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, -0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, -0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, -0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, -0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, -0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, -0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, -0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, -0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, -0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, -0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, -0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, -0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, -0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, -0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF -}; - diff --git a/dep/mysqllite/mysys/my_bitmap.c b/dep/mysqllite/mysys/my_bitmap.c deleted file mode 100644 index dc15014121b..00000000000 --- a/dep/mysqllite/mysys/my_bitmap.c +++ /dev/null @@ -1,932 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* - Handling of uchar arrays as large bitmaps. - - API limitations (or, rather asserted safety assumptions, - to encourage correct programming) - - * 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_* - - 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> -#include <my_bit.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))) -{ - if (map->mutex) - mysql_mutex_lock(map->mutex); -} - -static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) -{ - if (map->mutex) - mysql_mutex_unlock(map->mutex); -} - - -my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, - my_bool thread_safe __attribute__((unused))) -{ - DBUG_ENTER("bitmap_init"); - if (!buf) - { - uint size_in_bytes= bitmap_buffer_size(n_bits); - uint extra= 0; - - if (thread_safe) - { - size_in_bytes= ALIGN_SIZE(size_in_bytes); - extra= sizeof(mysql_mutex_t); - } - map->mutex= 0; - - if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME)))) - DBUG_RETURN(1); - - if (thread_safe) - { - map->mutex= (mysql_mutex_t *) ((char*) buf + size_in_bytes); - mysql_mutex_init(key_BITMAP_mutex, map->mutex, MY_MUTEX_INIT_FAST); - } - - } - - else - { - DBUG_ASSERT(thread_safe == 0); - } - - - map->bitmap= buf; - map->n_bits= n_bits; - create_last_word_mask(map); - bitmap_clear_all(map); - DBUG_RETURN(0); -} - - -void bitmap_free(MY_BITMAP *map) -{ - DBUG_ENTER("bitmap_free"); - if (map->bitmap) - { - if (map->mutex) - mysql_mutex_destroy(map->mutex); - - my_free(map->bitmap); - map->bitmap=0; - } - DBUG_VOID_RETURN; -} - - -/* - test if bit already set and set it if it was not (thread unsafe method) - - SYNOPSIS - bitmap_fast_test_and_set() - MAP bit map struct - BIT bit number - - RETURN - 0 bit was not set - !=0 bit was set -*/ - -my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) -{ - uchar *value= ((uchar*) map->bitmap) + (bitmap_bit / 8); - uchar bit= 1 << ((bitmap_bit) & 7); - uchar res= (*value) & bit; - *value|= bit; - return res; -} - - -/* - test if bit already set and set it if it was not (thread safe method) - - SYNOPSIS - bitmap_fast_test_and_set() - map bit map struct - bitmap_bit bit number - - RETURN - 0 bit was not set - !=0 bit was set -*/ - -my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) -{ - my_bool res; - 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; -} - -/* - test if bit already set and clear it if it was set(thread unsafe method) - - SYNOPSIS - bitmap_fast_test_and_set() - MAP bit map struct - BIT bit number - - RETURN - 0 bit was not set - !=0 bit was set -*/ - -my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) -{ - uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8); - uchar bit= 1 << ((bitmap_bit) & 7); - uchar res= (*byte) & bit; - *byte&= ~bit; - return res; -} - - -my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) -{ - my_bool res; - DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); - bitmap_lock(map); - res= bitmap_fast_test_and_clear(map, bitmap_bit); - bitmap_unlock(map); - return res; -} - - -uint bitmap_set_next(MY_BITMAP *map) -{ - 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_prefix(MY_BITMAP *map, uint prefix_size) -{ - uint prefix_bytes, prefix_bits, d; - uchar *m= (uchar *)map->bitmap; - - DBUG_ASSERT(map->bitmap && - (prefix_size <= map->n_bits || prefix_size == (uint) ~0)); - 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 & 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); - - while (m < end_prefix) - if (*m++ != 0xff) - 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; -ret: - return res; -} - - -my_bool bitmap_is_set_all(const MY_BITMAP *map) -{ - 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_clear_all(const MY_BITMAP *map) -{ - 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) -{ - my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); - - 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 0; - } - return 1; -} - -/* True if bitmaps has any common bits */ - -my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) -{ - my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; - - DBUG_ASSERT(map1->bitmap && map2->bitmap && - map1->n_bits==map2->n_bits); - - 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) -{ - 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); - - end= to+min(len,len2); - *map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/ - while (to < end) - *to++ &= *from++; - - if (len2 < len) - { - end+=len-len2; - while (to < end) - *to++=0; - } -} - - -/* - Set/clear all bits above a bit. - - SYNOPSIS - bitmap_set_above() - map RETURN The bitmap to change. - from_byte The bitmap buffer byte offset to start with. - use_bit The bit value (1/0) to use for all upper bits. - - NOTE - You can only set/clear full bytes. - The function is meant for the situation that you copy a smaller bitmap - to a bigger bitmap. Bitmap lengths are always multiple of eigth (the - size of a byte). Using 'from_byte' saves multiplication and division - by eight during parameter passing. - - RETURN - void -*/ - -void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) -{ - uchar use_byte= use_bit ? 0xff : 0; - uchar *to= (uchar *)map->bitmap + from_byte; - uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8; - - while (to < end) - *to++= use_byte; -} - - -void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) -{ - my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && - map->n_bits==map2->n_bits); - - 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->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; - } - } - } - } - } - 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; - } - } - } - } - } - return MY_BIT_NONE; -} - - -uint bitmap_lock_set_next(MY_BITMAP *map) -{ - uint bit_found; - bitmap_lock(map); - bit_found= bitmap_set_next(map); - bitmap_unlock(map); - return bit_found; -} - - -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); -} - -#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) -{ - 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; -} - -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++) - { - 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); - } - 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/dep/mysqllite/mysys/my_chsize.c b/dep/mysqllite/mysys/my_chsize.c deleted file mode 100644 index b9013811b34..00000000000 --- a/dep/mysqllite/mysys/my_chsize.c +++ /dev/null @@ -1,107 +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" -#include "m_string.h" - -/* - Change size of file. - - SYNOPSIS - my_chsize() - fd File descriptor - new_length New file size - filler If we don't have truncate, fill up all bytes after - new_length with this character - MyFlags Flags - - DESCRIPTION - my_chsize() truncates file if shorter else fill with the filler character. - The function also changes the file pointer. Usually it points to the end - of the file after execution. - - RETURN VALUE - 0 Ok - 1 Error -*/ -int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags) -{ - my_off_t oldsize; - uchar buff[IO_SIZE]; - DBUG_ENTER("my_chsize"); - DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength, - MyFlags)); - - if ((oldsize= my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength) - DBUG_RETURN(0); - - DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize)); - - if (oldsize > newlength) - { -#ifdef _WIN32 - if (my_win_chsize(fd, newlength)) - { - my_errno= errno; - goto err; - } - DBUG_RETURN(0); -#elif defined(HAVE_FTRUNCATE) - if (ftruncate(fd, (off_t) newlength)) - { - my_errno= errno; - goto err; - } - DBUG_RETURN(0); -#elif defined(HAVE_CHSIZE) - if (chsize(fd, (off_t) newlength)) - { - my_errno=errno; - goto err; - } - DBUG_RETURN(0); -#else - /* - Fill space between requested length and true length with 'filler' - We should never come here on any modern machine - */ - if (my_seek(fd, newlength, MY_SEEK_SET, MYF(MY_WME+MY_FAE)) - == MY_FILEPOS_ERROR) - { - goto err; - } - swap_variables(my_off_t, newlength, oldsize); -#endif - } - - /* Full file with 'filler' until it's as big as requested */ - bfill(buff, IO_SIZE, filler); - while (newlength-oldsize > IO_SIZE) - { - if (my_write(fd, buff, IO_SIZE, MYF(MY_NABP))) - goto err; - oldsize+= IO_SIZE; - } - if (my_write(fd,buff,(size_t) (newlength-oldsize), MYF(MY_NABP))) - goto err; - DBUG_RETURN(0); - -err: - DBUG_PRINT("error", ("errno: %d", errno)); - if (MyFlags & MY_WME) - my_error(EE_CANT_CHSIZE, MYF(ME_BELL+ME_WAITTANG), my_errno); - DBUG_RETURN(1); -} /* my_chsize */ diff --git a/dep/mysqllite/mysys/my_compress.c b/dep/mysqllite/mysys/my_compress.c deleted file mode 100644 index 360390d376a..00000000000 --- a/dep/mysqllite/mysys/my_compress.c +++ /dev/null @@ -1,264 +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 */ - -/* Written by Sinisa Milivojevic <sinisa@mysql.com> */ - -#include <my_global.h> -#ifdef HAVE_COMPRESS -#include <my_sys.h> -#ifndef SCO -#include <m_string.h> -#endif -#include <zlib.h> - -/* - This replaces the packet with a compressed packet - - SYNOPSIS - my_compress() - packet Data to compress. This is is replaced with the compressed data. - len Length of data to compress at 'packet' - complen out: 0 if packet was not compressed - - RETURN - 1 error. 'len' is not changed' - 0 ok. In this case 'len' contains the size of the compressed packet -*/ - -my_bool my_compress(uchar *packet, size_t *len, size_t *complen) -{ - DBUG_ENTER("my_compress"); - if (*len < MIN_COMPRESS_LENGTH) - { - *complen=0; - DBUG_PRINT("note",("Packet too short: Not compressed")); - } - else - { - uchar *compbuf=my_compress_alloc(packet,len,complen); - if (!compbuf) - DBUG_RETURN(*complen ? 0 : 1); - memcpy(packet,compbuf,*len); - my_free(compbuf); - } - DBUG_RETURN(0); -} - - -uchar *my_compress_alloc(const uchar *packet, size_t *len, size_t *complen) -{ - uchar *compbuf; - uLongf tmp_complen; - int res; - *complen= *len * 120 / 100 + 12; - - if (!(compbuf= (uchar *) my_malloc(*complen, MYF(MY_WME)))) - return 0; /* Not enough memory */ - - tmp_complen= (uint) *complen; - res= compress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, (uLong) *len); - *complen= tmp_complen; - - if (res != Z_OK) - { - my_free(compbuf); - return 0; - } - - if (*complen >= *len) - { - *complen= 0; - my_free(compbuf); - DBUG_PRINT("note",("Packet got longer on compression; Not compressed")); - return 0; - } - /* Store length of compressed packet in *len */ - swap_variables(size_t, *len, *complen); - return compbuf; -} - - -/* - Uncompress packet - - SYNOPSIS - my_uncompress() - packet Compressed data. This is is replaced with the orignal data. - len Length of compressed data - complen Length of the packet buffer (must be enough for the original - data) - - RETURN - 1 error - 0 ok. In this case 'complen' contains the updated size of the - real data. -*/ - -my_bool my_uncompress(uchar *packet, size_t len, size_t *complen) -{ - uLongf tmp_complen; - DBUG_ENTER("my_uncompress"); - - if (*complen) /* If compressed */ - { - uchar *compbuf= (uchar *) my_malloc(*complen,MYF(MY_WME)); - int error; - if (!compbuf) - DBUG_RETURN(1); /* Not enough memory */ - - tmp_complen= (uint) *complen; - error= uncompress((Bytef*) compbuf, &tmp_complen, (Bytef*) packet, - (uLong) len); - *complen= tmp_complen; - if (error != Z_OK) - { /* Probably wrong packet */ - DBUG_PRINT("error",("Can't uncompress packet, error: %d",error)); - my_free(compbuf); - DBUG_RETURN(1); - } - memcpy(packet, compbuf, *complen); - my_free(compbuf); - } - else - *complen= len; - DBUG_RETURN(0); -} - -/* - Internal representation of the frm blob is: - - ver 4 bytes - orglen 4 bytes - complen 4 bytes -*/ - -#define BLOB_HEADER 12 - - -/* - 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 - - NOTES - data is replaced with compressed content - - RETURN VALUES - 0 Success - >0 Failure -*/ - -int packfrm(uchar *data, size_t len, - uchar **pack_data, size_t *pack_len) -{ - int error; - size_t org_len, comp_len, blob_len; - uchar *blob; - DBUG_ENTER("packfrm"); - DBUG_PRINT("enter", ("data: 0x%lx len: %lu", (long) data, (ulong) len)); - - error= 1; - org_len= len; - if (my_compress((uchar*)data, &org_len, &comp_len)) - goto err; - - DBUG_PRINT("info", ("org_len: %lu comp_len: %lu", (ulong) org_len, - (ulong) comp_len)); - DBUG_DUMP("compressed", data, org_len); - - error= 2; - blob_len= BLOB_HEADER + org_len; - if (!(blob= (uchar*) my_malloc(blob_len,MYF(MY_WME)))) - goto err; - - /* Store compressed blob in machine independent format */ - int4store(blob, 1); - int4store(blob+4, (uint32) len); - int4store(blob+8, (uint32) org_len); /* compressed length */ - - /* Copy frm data into blob, already in machine independent format */ - memcpy(blob+BLOB_HEADER, data, org_len); - - *pack_data= blob; - *pack_len= blob_len; - error= 0; - - DBUG_PRINT("exit", ("pack_data: 0x%lx pack_len: %lu", - (long) *pack_data, (ulong) *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(uchar **unpack_data, size_t *unpack_len, - const uchar *pack_data) -{ - uchar *data; - size_t complen, orglen; - ulong ver; - DBUG_ENTER("unpackfrm"); - DBUG_PRINT("enter", ("pack_data: 0x%lx", (long) pack_data)); - - ver= uint4korr(pack_data); - orglen= uint4korr(pack_data+4); - complen= uint4korr(pack_data+8); - - DBUG_PRINT("blob",("ver: %lu complen: %lu orglen: %lu", - ver, (ulong) complen, (ulong) orglen)); - DBUG_DUMP("blob->data", pack_data + BLOB_HEADER, complen); - - if (ver != 1) - DBUG_RETURN(1); - if (!(data= my_malloc(max(orglen, complen), MYF(MY_WME)))) - DBUG_RETURN(2); - memcpy(data, pack_data + BLOB_HEADER, complen); - - if (my_uncompress(data, complen, &orglen)) - { - my_free(data); - DBUG_RETURN(3); - } - - *unpack_data= data; - *unpack_len= orglen; - - DBUG_PRINT("exit", ("frmdata: 0x%lx len: %lu", (long) *unpack_data, - (ulong) *unpack_len)); - DBUG_RETURN(0); -} -#endif /* HAVE_COMPRESS */ diff --git a/dep/mysqllite/mysys/my_conio.c b/dep/mysqllite/mysys/my_conio.c deleted file mode 100644 index 5dbd31193a9..00000000000 --- a/dep/mysqllite/mysys/my_conio.c +++ /dev/null @@ -1,222 +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" - -#ifdef __WIN__ - -static HANDLE my_coninpfh= 0; /* console input */ - -/* - functions my_pthread_auto_mutex_lock & my_pthread_auto_mutex_free - are experimental at this moment, they are intended to bring - ability of protecting code sections without necessity to explicitly - initialize synchronization object in one of threads - - if found useful they are to be exported in mysys -*/ - - -/* - int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, - int id, int time) - NOTES - creates a mutex with given name and tries to lock it time msec. - mutex name is appended with id to allow system wide or process wide - locks. Handle to created mutex returned in ph argument. - - RETURN - 0 thread owns mutex - <>0 error -*/ - -static -int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, int id, int time) -{ - int res; - char tname[FN_REFLEN]; - - sprintf(tname, "%s-%08X", name, id); - - *ph= CreateMutex(NULL, FALSE, tname); - if (*ph == NULL) - return GetLastError(); - - res= WaitForSingleObject(*ph, time); - - if (res == WAIT_TIMEOUT) - return ERROR_SEM_TIMEOUT; - - if (res == WAIT_FAILED) - return GetLastError(); - - return 0; -} - -/* - int my_pthread_auto_mutex_free(HANDLE* ph) - - NOTES - releases a mutex. - - RETURN - 0 thread released mutex - <>0 error - -*/ -static -int my_pthread_auto_mutex_free(HANDLE* ph) -{ - if (*ph) - { - ReleaseMutex(*ph); - CloseHandle(*ph); - *ph= NULL; - } - - return 0; -} - - -#define pthread_auto_mutex_decl(name) \ - HANDLE __h##name= NULL; - -#define pthread_auto_mutex_lock(name, proc, time) \ - my_pthread_auto_mutex_lock(&__h##name, #name, (proc), (time)) - -#define pthread_auto_mutex_free(name) \ - my_pthread_auto_mutex_free(&__h##name) - - -/* - char* my_cgets() - - NOTES - Replaces _cgets from libc to support input of more than 255 chars. - Reads from the console via ReadConsole into buffer which - should be at least clen characters. - Actual length of string returned in plen. - - WARNING - my_cgets() does NOT check the pushback character buffer (i.e., _chbuf). - Thus, my_cgets() will not return any character that is pushed back by - the _ungetch() call. - - RETURN - string pointer ok - NULL Error - -*/ - -char* my_cgets(char *buffer, size_t clen, size_t* plen) -{ - ULONG state; - char *result; - DWORD plen_res; - CONSOLE_SCREEN_BUFFER_INFO csbi; - - pthread_auto_mutex_decl(my_conio_cs); - - /* lock the console for the current process*/ - if (pthread_auto_mutex_lock(my_conio_cs, GetCurrentProcessId(), INFINITE)) - { - /* can not lock console */ - pthread_auto_mutex_free(my_conio_cs); - return NULL; - } - - /* init console input */ - if (my_coninpfh == 0) - { - /* same handle will be used until process termination */ - my_coninpfh= CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - } - - if (my_coninpfh == INVALID_HANDLE_VALUE) - { - /* unlock the console */ - pthread_auto_mutex_free(my_conio_cs); - return(NULL); - } - - GetConsoleMode((HANDLE)my_coninpfh, &state); - SetConsoleMode((HANDLE)my_coninpfh, ENABLE_LINE_INPUT | - ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT); - - GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); - - /* - there is no known way to determine allowed buffer size for input - though it is known it should not be more than 64K - so we cut 64K and try first size of screen buffer - if it is still to large we cut half of it and try again - later we may want to cycle from min(clen, 65535) to allowed size - with small decrement to determine exact allowed buffer - */ - clen= min(clen, 65535); - do - { - clen= min(clen, (size_t) csbi.dwSize.X*csbi.dwSize.Y); - if (!ReadConsole((HANDLE)my_coninpfh, (LPVOID)buffer, (DWORD) clen - 1, &plen_res, - NULL)) - { - result= NULL; - clen>>= 1; - } - else - { - result= buffer; - break; - } - } - while (GetLastError() == ERROR_NOT_ENOUGH_MEMORY); - *plen= plen_res; - - /* We go here on error reading the string (Ctrl-C for example) */ - if (!*plen) - result= NULL; /* purecov: inspected */ - - if (result != NULL) - { - if (*plen > 1 && buffer[*plen - 2] == '\r') - { - *plen= *plen - 2; - } - else - { - if (*plen > 0 && buffer[*plen - 1] == '\r') - { - char tmp[3]; - int tmplen= sizeof(tmp); - - *plen= *plen - 1; - /* read /n left in the buffer */ - ReadConsole((HANDLE)my_coninpfh, (LPVOID)tmp, tmplen, &tmplen, NULL); - } - } - buffer[*plen]= '\0'; - } - - SetConsoleMode((HANDLE)my_coninpfh, state); - /* unlock the console */ - pthread_auto_mutex_free(my_conio_cs); - - return result; -} - -#endif /* __WIN__ */ diff --git a/dep/mysqllite/mysys/my_copy.c b/dep/mysqllite/mysys/my_copy.c deleted file mode 100644 index 35324dd4cef..00000000000 --- a/dep/mysqllite/mysys/my_copy.c +++ /dev/null @@ -1,144 +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 <my_dir.h> /* for stat */ -#include <m_string.h> -#include "mysys_err.h" -#if defined(HAVE_UTIME_H) -#include <utime.h> -#elif defined(HAVE_SYS_UTIME_H) -#include <sys/utime.h> -#elif !defined(HPUX10) -#include <time.h> -struct utimbuf { - time_t actime; - time_t modtime; -}; -#endif - - -/* - int my_copy(const char *from, const char *to, myf MyFlags) - - NOTES - Ordinary ownership and accesstimes are copied from 'from-file' - If MyFlags & MY_HOLD_ORIGINAL_MODES is set and to-file exists then - the modes of to-file isn't changed - If MyFlags & MY_DONT_OVERWRITE_FILE is set, we will give an error - if the file existed. - - WARNING - Don't set MY_FNABP or MY_NABP bits on when calling this function ! - - RETURN - 0 ok - # Error - -*/ - -int my_copy(const char *from, const char *to, myf MyFlags) -{ - size_t Count; - my_bool new_file_stat= 0; /* 1 if we could stat "to" */ - int create_flag; - File from_file,to_file; - uchar buff[IO_SIZE]; - MY_STAT stat_buff,new_stat_buff; - DBUG_ENTER("my_copy"); - DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); - - from_file=to_file= -1; - DBUG_ASSERT(!(MyFlags & (MY_FNABP | MY_NABP))); /* for my_read/my_write */ - if (MyFlags & MY_HOLD_ORIGINAL_MODES) /* Copy stat if possible */ - new_file_stat= test(my_stat((char*) to, &new_stat_buff, MYF(0))); - - if ((from_file=my_open(from,O_RDONLY | O_SHARE,MyFlags)) >= 0) - { - if (!my_stat(from, &stat_buff, MyFlags)) - { - my_errno=errno; - goto err; - } - if (MyFlags & MY_HOLD_ORIGINAL_MODES && new_file_stat) - stat_buff=new_stat_buff; - create_flag= (MyFlags & MY_DONT_OVERWRITE_FILE) ? O_EXCL : O_TRUNC; - - if ((to_file= my_create(to,(int) stat_buff.st_mode, - O_WRONLY | create_flag | O_BINARY | O_SHARE, - MyFlags)) < 0) - goto err; - - while ((Count=my_read(from_file, buff, sizeof(buff), MyFlags)) != 0) - { - if (Count == (uint) -1 || - my_write(to_file,buff,Count,MYF(MyFlags | MY_NABP))) - goto err; - } - - /* sync the destination file */ - if (MyFlags & MY_SYNC) - { - if (my_sync(to_file, MyFlags)) - goto err; - } - - if (my_close(from_file,MyFlags) | my_close(to_file,MyFlags)) - DBUG_RETURN(-1); /* Error on close */ - - /* Copy modes if possible */ - - if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat) - DBUG_RETURN(0); /* File copyed but not stat */ - /* Copy modes */ - if (chmod(to, stat_buff.st_mode & 07777)) - { - my_errno= errno; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL+ME_WAITTANG), from, errno); - goto err; - } -#if !defined(__WIN__) - /* Copy ownership */ - if (chown(to, stat_buff.st_uid, stat_buff.st_gid)) - { - my_errno= errno; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_CHANGE_OWNERSHIP, MYF(ME_BELL+ME_WAITTANG), from, errno); - goto err; - } -#endif - - if (MyFlags & MY_COPYTIME) - { - struct utimbuf timep; - timep.actime = stat_buff.st_atime; - timep.modtime = stat_buff.st_mtime; - (void) utime((char*) to, &timep); /* last accessed and modified times */ - } - - DBUG_RETURN(0); - } - -err: - if (from_file >= 0) (void) my_close(from_file,MyFlags); - if (to_file >= 0) - { - (void) my_close(to_file, MyFlags); - /* attempt to delete the to-file we've partially written */ - (void) my_delete(to, MyFlags); - } - DBUG_RETURN(-1); -} /* my_copy */ diff --git a/dep/mysqllite/mysys/my_create.c b/dep/mysqllite/mysys/my_create.c deleted file mode 100644 index 49529f9b7b5..00000000000 --- a/dep/mysqllite/mysys/my_create.c +++ /dev/null @@ -1,73 +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 <my_dir.h> -#include "mysys_err.h" -#include <errno.h> -#include <my_sys.h> -#if defined(_WIN32) -#include <share.h> -#endif - - /* - ** Create a new file - ** Arguments: - ** Path-name of file - ** Read | write on file (umask value) - ** Read & Write on open file - ** Special flags - */ - - -File my_create(const char *FileName, int CreateFlags, int access_flags, - myf MyFlags) -{ - int fd, rc; - DBUG_ENTER("my_create"); - DBUG_PRINT("my",("Name: '%s' CreateFlags: %d AccessFlags: %d MyFlags: %d", - FileName, CreateFlags, access_flags, MyFlags)); -#if defined(_WIN32) - fd= my_win_open(FileName, access_flags | O_CREAT); -#else - fd= open((char *) FileName, access_flags | O_CREAT, - CreateFlags ? CreateFlags : my_umask); -#endif - - if ((MyFlags & MY_SYNC_DIR) && (fd >=0) && - my_sync_dir_by_file(FileName, MyFlags)) - { - my_close(fd, MyFlags); - fd= -1; - } - - rc= my_register_filename(fd, FileName, FILE_BY_CREATE, - EE_CANTCREATEFILE, MyFlags); - /* - my_register_filename() may fail on some platforms even if the call to - *open() above succeeds. In this case, don't leave the stale file because - callers assume the file to not exist if my_create() fails, so they don't - do any cleanups. - */ - if (unlikely(fd >= 0 && rc < 0)) - { - int tmp= my_errno; - my_close(fd, MyFlags); - my_delete(FileName, MyFlags); - my_errno= tmp; - } - - DBUG_RETURN(rc); -} /* my_create */ diff --git a/dep/mysqllite/mysys/my_delete.c b/dep/mysqllite/mysys/my_delete.c deleted file mode 100644 index 4a23fedb5ab..00000000000 --- a/dep/mysqllite/mysys/my_delete.c +++ /dev/null @@ -1,125 +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" -#include <my_sys.h> - -int my_delete(const char *name, myf MyFlags) -{ - int err; - DBUG_ENTER("my_delete"); - DBUG_PRINT("my",("name %s MyFlags %d", name, MyFlags)); - - if ((err = unlink(name)) == -1) - { - my_errno=errno; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_DELETE,MYF(ME_BELL+ME_WAITTANG+(MyFlags & ME_NOINPUT)), - name,errno); - } - else if ((MyFlags & MY_SYNC_DIR) && - my_sync_dir_by_file(name, MyFlags)) - err= -1; - DBUG_RETURN(err); -} /* my_delete */ - -#if defined(__WIN__) -/** - Delete file which is possibly not closed. - - This function is intended to be used exclusively as a temporal solution - for Win NT in case when it is needed to delete a not closed file (note - that the file must be opened everywhere with FILE_SHARE_DELETE mode). - Deleting not-closed files can not be supported on Win 98|ME (and because - of that is considered harmful). - - The function deletes the file with its preliminary renaming. This is - because when not-closed share-delete file is deleted it still lives on - a disk until it will not be closed everwhere. This may conflict with an - attempt to create a new file with the same name. The deleted file is - renamed to <name>.<num>.deleted where <name> - the initial name of the - file, <num> - a hexadecimal number chosen to make the temporal name to - be unique. - - @param the name of the being deleted file - @param the flags instructing how to react on an error internally in - the function - - @note The per-thread @c my_errno holds additional info for a caller to - decide how critical the error can be. - - @retval - 0 ok - @retval - 1 error - - -*/ -int nt_share_delete(const char *name, myf MyFlags) -{ - char buf[MAX_PATH + 20]; - ulong cnt; - DBUG_ENTER("nt_share_delete"); - DBUG_PRINT("my",("name %s MyFlags %d", name, MyFlags)); - - for (cnt= GetTickCount(); cnt; cnt--) - { - errno= 0; - sprintf(buf, "%s.%08X.deleted", name, cnt); - if (MoveFile(name, buf)) - break; - - if ((errno= GetLastError()) == ERROR_ALREADY_EXISTS) - continue; - - /* This happened during tests with MERGE tables. */ - if (errno == ERROR_ACCESS_DENIED) - continue; - - DBUG_PRINT("warning", ("Failed to rename %s to %s, errno: %d", - name, buf, errno)); - break; - } - - if (errno == ERROR_FILE_NOT_FOUND) - { - my_errno= ENOENT; // marking, that `name' doesn't exist - } - else if (errno == 0) - { - if (DeleteFile(buf)) - DBUG_RETURN(0); - /* - The below is more complicated than necessary. For some reason, the - assignment to my_errno clears the error number, which is retrieved - by GetLastError() (VC2005EE). Assigning to errno first, allows to - retrieve the correct value. - */ - errno= GetLastError(); - if (errno == 0) - my_errno= ENOENT; // marking, that `buf' doesn't exist - else - my_errno= errno; - } - else - my_errno= errno; - - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_DELETE, MYF(ME_BELL + ME_WAITTANG + (MyFlags & ME_NOINPUT)), - name, my_errno); - DBUG_RETURN(-1); -} -#endif diff --git a/dep/mysqllite/mysys/my_div.c b/dep/mysqllite/mysys/my_div.c deleted file mode 100644 index d29d3668852..00000000000 --- a/dep/mysqllite/mysys/my_div.c +++ /dev/null @@ -1,37 +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" - -/* - Get filename of file - - SYNOPSIS - my_filename() - fd File descriptor -*/ - -char * my_filename(File fd) -{ - DBUG_ENTER("my_filename"); - if ((uint) fd >= (uint) my_file_limit) - DBUG_RETURN((char*) "UNKNOWN"); - if (fd >= 0 && my_file_info[fd].type != UNOPEN) - { - DBUG_RETURN(my_file_info[fd].name); - } - else - DBUG_RETURN((char*) "UNOPENED"); /* Debug message */ -} diff --git a/dep/mysqllite/mysys/my_error.c b/dep/mysqllite/mysys/my_error.c deleted file mode 100644 index fa62cc604b6..00000000000 --- a/dep/mysqllite/mysys/my_error.c +++ /dev/null @@ -1,290 +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" -#include <m_string.h> -#include <stdarg.h> -#include <m_ctype.h> - -/* Max length of a error message. Should be kept in sync with MYSQL_ERRMSG_SIZE. */ -#define ERRMSGSIZE (512) - -/* Define some external variables for error handling */ - -/* - WARNING! - my_error family functions have to be used according following rules: - - if message have not parameters use my_message(ER_CODE, ER(ER_CODE), MYF(N)) - - if message registered use my_error(ER_CODE, MYF(N), ...). - - With some special text of errror message use: - my_printf_error(ER_CODE, format, MYF(N), ...) -*/ - -/* - Message texts are registered into a linked list of 'my_err_head' structs. - Each struct contains (1.) an array of pointers to C character strings with - '\0' termination, (2.) the error number for the first message in the array - (array index 0) and (3.) the error number for the last message in the array - (array index (last - first)). - The array may contain gaps with NULL pointers and pointers to empty strings. - Both kinds of gaps will be translated to "Unknown error %d.", if my_error() - is called with a respective error number. - The list of header structs is sorted in increasing order of error numbers. - Negative error numbers are allowed. Overlap of error numbers is not allowed. - Not registered error numbers will be translated to "Unknown error %d.". -*/ -static struct my_err_head -{ - struct my_err_head *meh_next; /* chain link */ - const char** (*get_errmsgs) (); /* returns error message format */ - int meh_first; /* error number matching array slot 0 */ - int meh_last; /* error number matching last slot */ -} my_errmsgs_globerrs = {NULL, get_global_errmsgs, EE_ERROR_FIRST, EE_ERROR_LAST}; - -static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs; - - -/* - Error message to user - - SYNOPSIS - my_error() - nr Errno - MyFlags Flags - ... variable list - -*/ - -void my_error(int nr, myf MyFlags, ...) -{ - const char *format; - struct my_err_head *meh_p; - va_list args; - char ebuff[ERRMSGSIZE]; - 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. */ - for (meh_p= my_errmsgs_list; meh_p; meh_p= meh_p->meh_next) - if (nr <= meh_p->meh_last) - break; - - /* get the error message string. Default, if NULL or empty string (""). */ - if (! (format= (meh_p && (nr >= meh_p->meh_first)) ? - meh_p->get_errmsgs()[nr - meh_p->meh_first] : NULL) || ! *format) - (void) my_snprintf (ebuff, sizeof(ebuff), "Unknown error %d", nr); - else - { - va_start(args,MyFlags); - (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, - sizeof(ebuff), format, args); - va_end(args); - } - (*error_handler_hook)(nr, ebuff, MyFlags); - DBUG_VOID_RETURN; -} - - -/* - Error as printf - - SYNOPSIS - my_printf_error() - error Errno - format Format string - MyFlags Flags - ... variable list -*/ - -void my_printf_error(uint error, const char *format, myf MyFlags, ...) -{ - va_list args; - char ebuff[ERRMSGSIZE]; - DBUG_ENTER("my_printf_error"); - DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s", - error, MyFlags, errno, format)); - - va_start(args,MyFlags); - (void) my_vsnprintf_ex(&my_charset_utf8_general_ci, ebuff, - sizeof(ebuff), format, args); - va_end(args); - (*error_handler_hook)(error, ebuff, MyFlags); - DBUG_VOID_RETURN; -} - -/* - Error with va_list - - SYNOPSIS - my_printv_error() - error Errno - format Format string - MyFlags Flags - ... variable list -*/ - -void my_printv_error(uint error, const char *format, myf MyFlags, va_list ap) -{ - char ebuff[ERRMSGSIZE]; - DBUG_ENTER("my_printv_error"); - DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d format: %s", - error, MyFlags, errno, format)); - - (void) my_vsnprintf(ebuff, sizeof(ebuff), format, ap); - (*error_handler_hook)(error, ebuff, MyFlags); - DBUG_VOID_RETURN; -} - -/* - Give message using error_handler_hook - - SYNOPSIS - my_message() - error Errno - str Error message - MyFlags Flags -*/ - -void my_message(uint error, const char *str, register myf MyFlags) -{ - (*error_handler_hook)(error, str, MyFlags); -} - - -/* - Register error messages for use with my_error(). - - SYNOPSIS - my_error_register() - errmsgs array of pointers to error messages - first error number of first message in the array - last error number of last message in the array - - DESCRIPTION - The pointer array is expected to contain addresses to NUL-terminated - C character strings. The array contains (last - first + 1) pointers. - NULL pointers and empty strings ("") are allowed. These will be mapped to - "Unknown error" when my_error() is called with a matching error number. - This function registers the error numbers 'first' to 'last'. - No overlapping with previously registered error numbers is allowed. - - RETURN - 0 OK - != 0 Error -*/ - -int my_error_register(const char** (*get_errmsgs) (), int first, int last) -{ - struct my_err_head *meh_p; - struct my_err_head **search_meh_pp; - - /* Allocate a new header structure. */ - if (! (meh_p= (struct my_err_head*) my_malloc(sizeof(struct my_err_head), - MYF(MY_WME)))) - return 1; - meh_p->get_errmsgs= get_errmsgs; - meh_p->meh_first= first; - meh_p->meh_last= last; - - /* Search for the right position in the list. */ - for (search_meh_pp= &my_errmsgs_list; - *search_meh_pp; - search_meh_pp= &(*search_meh_pp)->meh_next) - { - if ((*search_meh_pp)->meh_last > first) - break; - } - - /* Error numbers must be unique. No overlapping is allowed. */ - if (*search_meh_pp && ((*search_meh_pp)->meh_first <= last)) - { - my_free(meh_p); - return 1; - } - - /* Insert header into the chain. */ - meh_p->meh_next= *search_meh_pp; - *search_meh_pp= meh_p; - return 0; -} - - -/* - Unregister formerly registered error messages. - - SYNOPSIS - my_error_unregister() - first error number of first message - last error number of last message - - DESCRIPTION - This function unregisters the error numbers 'first' to 'last'. - These must have been previously registered by my_error_register(). - 'first' and 'last' must exactly match the registration. - If a matching registration is present, the header is removed from the - list and the pointer to the error messages pointers array is returned. - Otherwise, NULL is returned. - - RETURN - non-NULL OK, returns address of error messages pointers array. - NULL Error, no such number range registered. -*/ - -const char **my_error_unregister(int first, int last) -{ - struct my_err_head *meh_p; - struct my_err_head **search_meh_pp; - const char **errmsgs; - - /* Search for the registration in the list. */ - for (search_meh_pp= &my_errmsgs_list; - *search_meh_pp; - search_meh_pp= &(*search_meh_pp)->meh_next) - { - if (((*search_meh_pp)->meh_first == first) && - ((*search_meh_pp)->meh_last == last)) - break; - } - if (! *search_meh_pp) - return NULL; - - /* Remove header from the chain. */ - meh_p= *search_meh_pp; - *search_meh_pp= meh_p->meh_next; - - /* Save the return value and free the header. */ - errmsgs= meh_p->get_errmsgs(); - my_free(meh_p); - - return errmsgs; -} - - -void my_error_unregister_all(void) -{ - struct my_err_head *cursor, *saved_next; - - for (cursor= my_errmsgs_globerrs.meh_next; cursor != NULL; cursor= saved_next) - { - /* We need this ptr, but we're about to free its container, so save it. */ - saved_next= cursor->meh_next; - - my_free(cursor); - } - my_errmsgs_globerrs.meh_next= NULL; /* Freed in first iteration above. */ - - my_errmsgs_list= &my_errmsgs_globerrs; -} diff --git a/dep/mysqllite/mysys/my_file.c b/dep/mysqllite/mysys/my_file.c deleted file mode 100644 index e4b7cd7779f..00000000000 --- a/dep/mysqllite/mysys/my_file.c +++ /dev/null @@ -1,135 +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 "my_static.h" -#include <m_string.h> - -/* - set how many open files we want to be able to handle - - SYNOPSIS - set_maximum_open_files() - max_file_limit Files to open - - NOTES - The request may not fulfilled becasue of system limitations - - RETURN - Files available to open. - May be more or less than max_file_limit! -*/ - -#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) - -#ifndef RLIM_INFINITY -#define RLIM_INFINITY ((uint) 0xffffffff) -#endif - -static uint set_max_open_files(uint max_file_limit) -{ - struct rlimit rlimit; - uint old_cur; - DBUG_ENTER("set_max_open_files"); - DBUG_PRINT("enter",("files: %u", max_file_limit)); - - if (!getrlimit(RLIMIT_NOFILE,&rlimit)) - { - old_cur= (uint) rlimit.rlim_cur; - DBUG_PRINT("info", ("rlim_cur: %u rlim_max: %u", - (uint) rlimit.rlim_cur, - (uint) rlimit.rlim_max)); - if (rlimit.rlim_cur == RLIM_INFINITY) - rlimit.rlim_cur = max_file_limit; - if (rlimit.rlim_cur >= max_file_limit) - DBUG_RETURN(rlimit.rlim_cur); /* purecov: inspected */ - rlimit.rlim_cur= rlimit.rlim_max= max_file_limit; - if (setrlimit(RLIMIT_NOFILE, &rlimit)) - max_file_limit= old_cur; /* Use original value */ - else - { - rlimit.rlim_cur= 0; /* Safety if next call fails */ - (void) getrlimit(RLIMIT_NOFILE,&rlimit); - DBUG_PRINT("info", ("rlim_cur: %u", (uint) rlimit.rlim_cur)); - if (rlimit.rlim_cur) /* If call didn't fail */ - max_file_limit= (uint) rlimit.rlim_cur; - } - } - DBUG_PRINT("exit",("max_file_limit: %u", max_file_limit)); - DBUG_RETURN(max_file_limit); -} - -#else -static uint set_max_open_files(uint max_file_limit) -{ - /* We don't know the limit. Return best guess */ - return min(max_file_limit, OS_FILE_LIMIT); -} -#endif - - -/* - Change number of open files - - SYNOPSIS: - my_set_max_open_files() - files Number of requested files - - RETURN - number of files available for open -*/ - -uint my_set_max_open_files(uint files) -{ - struct st_my_file_info *tmp; - DBUG_ENTER("my_set_max_open_files"); - DBUG_PRINT("enter",("files: %u my_file_limit: %u", files, my_file_limit)); - - files+= MY_FILE_MIN; - files= set_max_open_files(min(files, OS_FILE_LIMIT)); - if (files <= MY_NFILE) - DBUG_RETURN(files); - - if (!(tmp= (struct st_my_file_info*) my_malloc(sizeof(*tmp) * files, - MYF(MY_WME)))) - DBUG_RETURN(MY_NFILE); - - /* Copy any initialized files */ - 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; - DBUG_PRINT("exit",("files: %u", files)); - DBUG_RETURN(files); -} - - -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(my_file_info); - my_file_info= my_file_info_default; - my_file_limit= MY_NFILE; - } - DBUG_VOID_RETURN; -} diff --git a/dep/mysqllite/mysys/my_fopen.c b/dep/mysqllite/mysys/my_fopen.c deleted file mode 100644 index e184c8308fc..00000000000 --- a/dep/mysqllite/mysys/my_fopen.c +++ /dev/null @@ -1,358 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 "my_static.h" -#include <errno.h> -#include "mysys_err.h" - -#if defined(__FreeBSD__) -extern int getosreldate(void); -#endif - -static void make_ftype(char * to,int flag); - -/* - Open a file as stream - - SYNOPSIS - my_fopen() - FileName Path-name of file - Flags Read | write | append | trunc (like for open()) - MyFlags Flags for handling errors - - RETURN - 0 Error - # File handler -*/ - -FILE *my_fopen(const char *filename, int flags, myf MyFlags) -{ - FILE *fd; - char type[5]; - DBUG_ENTER("my_fopen"); - DBUG_PRINT("my",("Name: '%s' flags: %d MyFlags: %d", - filename, flags, MyFlags)); - - make_ftype(type,flags); - -#ifdef _WIN32 - fd= my_win_fopen(filename, type); -#else - fd= fopen(filename, type); -#endif - if (fd != 0) - { - /* - The test works if MY_NFILE < 128. The problem is that fileno() is char - on some OS (SUNOS). Actually the filename save isn't that important - so we can ignore if this doesn't work. - */ - - int filedesc= my_fileno(fd); - if ((uint)filedesc >= my_file_limit) - { - thread_safe_increment(my_stream_opened,&THR_LOCK_open); - DBUG_RETURN(fd); /* safeguard */ - } - mysql_mutex_lock(&THR_LOCK_open); - if ((my_file_info[filedesc].name= (char*) - my_strdup(filename,MyFlags))) - { - my_stream_opened++; - my_file_total_opened++; - my_file_info[filedesc].type= STREAM_BY_FOPEN; - mysql_mutex_unlock(&THR_LOCK_open); - DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); - DBUG_RETURN(fd); - } - mysql_mutex_unlock(&THR_LOCK_open); - (void) my_fclose(fd,MyFlags); - my_errno=ENOMEM; - } - else - my_errno=errno; - DBUG_PRINT("error",("Got error %d on open",my_errno)); - if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) - my_error((flags & O_RDONLY) || (flags == O_RDONLY ) ? EE_FILENOTFOUND : - EE_CANTCREATEFILE, - MYF(ME_BELL+ME_WAITTANG), filename, my_errno); - DBUG_RETURN((FILE*) 0); -} /* my_fopen */ - - -#if defined(_WIN32) - -static FILE *my_win_freopen(const char *path, const char *mode, FILE *stream) -{ - int handle_fd, fd= _fileno(stream); - HANDLE osfh; - - DBUG_ASSERT(path && stream); - - /* Services don't have stdout/stderr on Windows, so _fileno returns -1. */ - if (fd < 0) - { - if (!freopen(path, mode, stream)) - return NULL; - - fd= _fileno(stream); - } - - if ((osfh= CreateFile(path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | - FILE_SHARE_DELETE, NULL, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, - NULL)) == INVALID_HANDLE_VALUE) - return NULL; - - if ((handle_fd= _open_osfhandle((intptr_t)osfh, - _O_APPEND | _O_TEXT)) == -1) - { - CloseHandle(osfh); - return NULL; - } - - if (_dup2(handle_fd, fd) < 0) - { - CloseHandle(osfh); - return NULL; - } - - _close(handle_fd); - - return stream; -} - -#elif defined(__FreeBSD__) - -/* No close operation hook. */ - -static int no_close(void *cookie __attribute__((unused))) -{ - return 0; -} - -/* - A hack around a race condition in the implementation of freopen. - - The race condition steams from the fact that the current fd of - the stream is closed before its number is used to duplicate the - new file descriptor. This defeats the desired atomicity of the - close and duplicate of dup2(). - - See PR number 79887 for reference: - http://www.freebsd.org/cgi/query-pr.cgi?pr=79887 -*/ - -static FILE *my_freebsd_freopen(const char *path, const char *mode, FILE *stream) -{ - int old_fd; - FILE *result; - - flockfile(stream); - - old_fd= fileno(stream); - - /* Use a no operation close hook to avoid having the fd closed. */ - stream->_close= no_close; - - /* Relies on the implicit dup2 to close old_fd. */ - result= freopen(path, mode, stream); - - /* If successful, the _close hook was replaced. */ - - if (result == NULL) - close(old_fd); - else - funlockfile(result); - - return result; -} - -#endif - - -/** - Change the file associated with a file stream. - - @param path Path to file. - @param mode Mode of the stream. - @param stream File stream. - - @note - This function is used to redirect stdout and stderr to a file and - subsequently to close and reopen that file for log rotation. - - @retval A FILE pointer on success. Otherwise, NULL. -*/ - -FILE *my_freopen(const char *path, const char *mode, FILE *stream) -{ - FILE *result; - -#if defined(_WIN32) - result= my_win_freopen(path, mode, stream); -#elif defined(__FreeBSD__) - /* - XXX: Once the fix is ported to the stable releases, this should - be dependent upon the specific FreeBSD versions. Check at: - http://www.freebsd.org/cgi/query-pr.cgi?pr=79887 - */ - if (getosreldate() > 900027) - result= freopen(path, mode, stream); - else - result= my_freebsd_freopen(path, mode, stream); -#else - result= freopen(path, mode, stream); -#endif - - return result; -} - - -/* Close a stream */ -int my_fclose(FILE *fd, myf MyFlags) -{ - int err,file; - DBUG_ENTER("my_fclose"); - DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) fd, MyFlags)); - - mysql_mutex_lock(&THR_LOCK_open); - file= my_fileno(fd); -#ifndef _WIN32 - err= fclose(fd); -#else - err= my_win_fclose(fd); -#endif - if(err < 0) - { - my_errno=errno; - if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_BADCLOSE, MYF(ME_BELL+ME_WAITTANG), - my_filename(file),errno); - } - else - my_stream_opened--; - if ((uint) file < my_file_limit && my_file_info[file].type != UNOPEN) - { - my_file_info[file].type = UNOPEN; - my_free(my_file_info[file].name); - } - mysql_mutex_unlock(&THR_LOCK_open); - DBUG_RETURN(err); -} /* my_fclose */ - - - /* Make a stream out of a file handle */ - /* Name may be 0 */ - -FILE *my_fdopen(File Filedes, const char *name, int Flags, myf MyFlags) -{ - FILE *fd; - char type[5]; - DBUG_ENTER("my_fdopen"); - DBUG_PRINT("my",("Fd: %d Flags: %d MyFlags: %d", - Filedes, Flags, MyFlags)); - - make_ftype(type,Flags); -#ifdef _WIN32 - fd= my_win_fdopen(Filedes, type); -#else - fd= fdopen(Filedes, type); -#endif - if (!fd) - { - my_errno=errno; - if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_CANT_OPEN_STREAM, MYF(ME_BELL+ME_WAITTANG),errno); - } - else - { - mysql_mutex_lock(&THR_LOCK_open); - my_stream_opened++; - if ((uint) Filedes < (uint) my_file_limit) - { - if (my_file_info[Filedes].type != UNOPEN) - { - my_file_opened--; /* File is opened with my_open ! */ - } - else - { - my_file_info[Filedes].name= my_strdup(name,MyFlags); - } - my_file_info[Filedes].type = STREAM_BY_FDOPEN; - } - mysql_mutex_unlock(&THR_LOCK_open); - } - - DBUG_PRINT("exit",("stream: 0x%lx", (long) fd)); - DBUG_RETURN(fd); -} /* my_fdopen */ - - -/* - Make a fopen() typestring from a open() type bitmap - - SYNOPSIS - make_ftype() - to String for fopen() is stored here - flag Flag used by open() - - IMPLEMENTATION - This routine attempts to find the best possible match - between a numeric option and a string option that could be - fed to fopen. There is not a 1 to 1 mapping between the two. - - NOTE - On Unix, O_RDONLY is usually 0 - - MAPPING - r == O_RDONLY - w == O_WRONLY|O_TRUNC|O_CREAT - a == O_WRONLY|O_APPEND|O_CREAT - r+ == O_RDWR - w+ == O_RDWR|O_TRUNC|O_CREAT - a+ == O_RDWR|O_APPEND|O_CREAT -*/ - -static void make_ftype(register char * to, register int flag) -{ - /* check some possible invalid combinations */ - DBUG_ASSERT((flag & (O_TRUNC | O_APPEND)) != (O_TRUNC | O_APPEND)); - DBUG_ASSERT((flag & (O_WRONLY | O_RDWR)) != (O_WRONLY | O_RDWR)); - - if ((flag & (O_RDONLY|O_WRONLY)) == O_WRONLY) - *to++= (flag & O_APPEND) ? 'a' : 'w'; - else if (flag & O_RDWR) - { - /* Add '+' after theese */ - if (flag & (O_TRUNC | O_CREAT)) - *to++= 'w'; - else if (flag & O_APPEND) - *to++= 'a'; - else - *to++= 'r'; - *to++= '+'; - } - else - *to++= 'r'; - -#if FILE_BINARY /* If we have binary-files */ - if (flag & FILE_BINARY) - *to++='b'; -#endif - *to='\0'; -} /* make_ftype */ diff --git a/dep/mysqllite/mysys/my_fstream.c b/dep/mysqllite/mysys/my_fstream.c deleted file mode 100644 index 83cb0d261c0..00000000000 --- a/dep/mysqllite/mysys/my_fstream.c +++ /dev/null @@ -1,194 +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 */ - -/* USE_MY_STREAM isn't set because we can't thrust my_fclose! */ - -#include "mysys_priv.h" -#include "mysys_err.h" -#include <errno.h> -#include <stdio.h> - -#ifdef HAVE_FSEEKO -#undef ftell -#undef fseek -#define ftell(A) ftello(A) -#define fseek(A,B,C) fseeko((A),(B),(C)) -#endif - -/* - Read a chunk of bytes from a FILE - - SYNOPSIS - my_fread() - stream File descriptor - Buffer Buffer to read to - Count Number of bytes to read - MyFlags Flags on what to do on error - - RETURN - (size_t) -1 Error - # Number of bytes read - */ - -size_t my_fread(FILE *stream, uchar *Buffer, size_t Count, myf MyFlags) -{ - size_t readbytes; - DBUG_ENTER("my_fread"); - DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d", - (long) stream, (long) Buffer, (uint) Count, MyFlags)); - - if ((readbytes= fread(Buffer, sizeof(char), Count, stream)) != Count) - { - DBUG_PRINT("error",("Read only %d bytes", (int) readbytes)); - if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) - { - if (ferror(stream)) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(my_fileno(stream)),errno); - else - if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(my_fileno(stream)),errno); - } - my_errno=errno ? errno : -1; - if (ferror(stream) || MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN((size_t) -1); /* Return with error */ - } - if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Read ok */ - DBUG_RETURN(readbytes); -} /* my_fread */ - - -/* - Write a chunk of bytes to a stream - - my_fwrite() - stream File descriptor - Buffer Buffer to write from - Count Number of bytes to write - MyFlags Flags on what to do on error - - RETURN - (size_t) -1 Error - # Number of bytes written -*/ - -size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags) -{ - size_t writtenbytes =0; - my_off_t seekptr; -#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) - uint errors; -#endif - DBUG_ENTER("my_fwrite"); - DBUG_PRINT("my",("stream: 0x%lx Buffer: 0x%lx Count: %u MyFlags: %d", - (long) stream, (long) Buffer, (uint) Count, MyFlags)); - -#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) - errors=0; -#endif - seekptr= ftell(stream); - for (;;) - { - size_t written; - if ((written = (size_t) fwrite((char*) Buffer,sizeof(char), - Count, stream)) != Count) - { - DBUG_PRINT("error",("Write only %d bytes", (int) writtenbytes)); - my_errno=errno; - if (written != (size_t) -1) - { - seekptr+=written; - Buffer+=written; - writtenbytes+=written; - Count-=written; - } -#ifdef EINTR - if (errno == EINTR) - { - (void) my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0)); - continue; - } -#endif -#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM) - if (my_thread_var->abort) - MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ - - if ((errno == ENOSPC || errno == EDQUOT) && - (MyFlags & MY_WAIT_IF_FULL)) - { - wait_for_free_space("[stream]", errors); - errors++; - (void) my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0)); - continue; - } -#endif - if (ferror(stream) || (MyFlags & (MY_NABP | MY_FNABP))) - { - if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) - { - my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG), - my_filename(my_fileno(stream)),errno); - } - writtenbytes= (size_t) -1; /* Return that we got error */ - break; - } - } - if (MyFlags & (MY_NABP | MY_FNABP)) - writtenbytes= 0; /* Everything OK */ - else - writtenbytes+= written; - break; - } - DBUG_RETURN(writtenbytes); -} /* my_fwrite */ - - -/* Seek to position in file */ - -my_off_t my_fseek(FILE *stream, my_off_t pos, int whence, - myf MyFlags __attribute__((unused))) -{ - DBUG_ENTER("my_fseek"); - DBUG_PRINT("my",("stream: 0x%lx pos: %lu whence: %d MyFlags: %d", - (long) stream, (long) pos, whence, MyFlags)); - DBUG_RETURN(fseek(stream, (off_t) pos, whence) ? - MY_FILEPOS_ERROR : (my_off_t) ftell(stream)); -} /* my_seek */ - - -/* Tell current position of file */ - -my_off_t my_ftell(FILE *stream, myf MyFlags __attribute__((unused))) -{ - off_t pos; - DBUG_ENTER("my_ftell"); - DBUG_PRINT("my",("stream: 0x%lx MyFlags: %d", (long) stream, MyFlags)); - pos=ftell(stream); - DBUG_PRINT("exit",("ftell: %lu",(ulong) pos)); - DBUG_RETURN((my_off_t) pos); -} /* my_ftell */ - - -/* Get a File corresponding to the stream*/ -int my_fileno(FILE *f) -{ -#ifdef _WIN32 - return my_win_fileno(f); -#else - return fileno(f); -#endif -} diff --git a/dep/mysqllite/mysys/my_gethostbyname.c b/dep/mysqllite/mysys/my_gethostbyname.c deleted file mode 100644 index 28ecec13ef2..00000000000 --- a/dep/mysqllite/mysys/my_gethostbyname.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (C) 2002, 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* Thread safe version of gethostbyname_r() */ - -#include "mysys_priv.h" -#if !defined(__WIN__) -#include <netdb.h> -#endif -#include <my_net.h> - -/* This file is not needed if my_gethostbyname_r is a macro */ -#if !defined(my_gethostbyname_r) - -/* - Emulate SOLARIS style calls, not because it's better, but just to make the - usage of getbostbyname_r simpler. -*/ - -#if defined(HAVE_GETHOSTBYNAME_R) - -#if defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE) - -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *result, char *buffer, - int buflen, int *h_errnop) -{ - struct hostent *hp; - DBUG_ASSERT((size_t) buflen >= sizeof(*result)); - if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop)) - return 0; - return hp; -} - -#elif defined(HAVE_GETHOSTBYNAME_R_RETURN_INT) - -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *result, char *buffer, - int buflen, int *h_errnop) -{ - if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1) - { - *h_errnop= errno; - return 0; - } - return result; -} - -#else - -/* gethostbyname_r with similar interface as gethostbyname() */ - -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *result, char *buffer, - int buflen, int *h_errnop) -{ - struct hostent *hp; - DBUG_ASSERT(buflen >= sizeof(struct hostent_data)); - hp= gethostbyname_r(name,result,(struct hostent_data *) buffer); - *h_errnop= errno; - return hp; -} -#endif /* GLIBC2_STYLE_GETHOSTBYNAME_R */ - -#else /* !HAVE_GETHOSTBYNAME_R */ - -extern mysql_mutex_t LOCK_gethostbyname_r; - -/* - No gethostbyname_r() function exists. - In this case we have to keep a mutex over the call to ensure that no - other thread is going to reuse the internal memory. - - The user is responsible to call my_gethostbyname_r_free() when he - is finished with the structure. -*/ - -struct hostent *my_gethostbyname_r(const char *name, - struct hostent *res __attribute__((unused)), - char *buffer __attribute__((unused)), - int buflen __attribute__((unused)), - int *h_errnop) -{ - struct hostent *hp; - mysql_mutex_lock(&LOCK_gethostbyname_r); - hp= gethostbyname(name); - *h_errnop= h_errno; - return hp; -} - -void my_gethostbyname_r_free() -{ - mysql_mutex_unlock(&LOCK_gethostbyname_r); -} - -#endif /* !HAVE_GETHOSTBYNAME_R */ -#endif /* !my_gethostbyname_r */ diff --git a/dep/mysqllite/mysys/my_gethwaddr.c b/dep/mysqllite/mysys/my_gethwaddr.c deleted file mode 100644 index ab44bac43d3..00000000000 --- a/dep/mysqllite/mysys/my_gethwaddr.c +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2004 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 hardware address for an interface */ -/* if there are many available, any non-zero one can be used */ - -#include "mysys_priv.h" -#include <m_string.h> - -#ifndef MAIN - -#ifdef __FreeBSD__ - -#include <net/ethernet.h> -#include <sys/sysctl.h> -#include <net/route.h> -#include <net/if.h> -#include <net/if_dl.h> - -my_bool my_gethwaddr(uchar *to) -{ - size_t len; - char *buf, *next, *end; - struct if_msghdr *ifm; - struct sockaddr_dl *sdl; - int res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0}; - char zero_array[ETHER_ADDR_LEN] = {0}; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) - goto err; - if (!(buf = alloca(len))) - goto err; - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) - goto err; - - end = buf + len; - - for (next = buf ; res && next < end ; next += ifm->ifm_msglen) - { - ifm = (struct if_msghdr *)next; - if (ifm->ifm_type == RTM_IFINFO) - { - sdl= (struct sockaddr_dl *)(ifm + 1); - memcpy(to, LLADDR(sdl), ETHER_ADDR_LEN); - res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1; - } - } - -err: - return res; -} - -#elif __linux__ - -#include <net/if.h> -#include <sys/ioctl.h> -#include <net/ethernet.h> - -my_bool my_gethwaddr(uchar *to) -{ - int fd, res= 1; - struct ifreq ifr; - char zero_array[ETHER_ADDR_LEN] = {0}; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) - goto err; - - bzero(&ifr, sizeof(ifr)); - strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1); - - do - { - if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) - { - memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); - res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1; - } - } while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6'); - - close(fd); -err: - return res; -} - -#elif defined(__WIN__) - -/* - Workaround for BUG#32082 (Definition of VOID in my_global.h conflicts with - windows headers) -*/ -#ifdef VOID -#undef VOID -#define VOID void -#endif - -#include <iphlpapi.h> - -/* - The following typedef is for dynamically loading iphlpapi.dll / - GetAdaptersAddresses. Dynamic loading is used because - GetAdaptersAddresses is not available on Windows 2000 which MySQL - still supports. Static linking would cause an unresolved export. -*/ -typedef DWORD (WINAPI *pfnGetAdaptersAddresses)(IN ULONG Family, - IN DWORD Flags,IN PVOID Reserved, - OUT PIP_ADAPTER_ADDRESSES pAdapterAddresses, - IN OUT PULONG pOutBufLen); - -/* - my_gethwaddr - Windows version - - @brief Retrieve MAC address from network hardware - - @param[out] to MAC address exactly six bytes - - @return Operation status - @retval 0 OK - @retval <>0 FAILED -*/ -my_bool my_gethwaddr(uchar *to) -{ - PIP_ADAPTER_ADDRESSES pAdapterAddresses; - PIP_ADAPTER_ADDRESSES pCurrAddresses; - IP_ADAPTER_ADDRESSES adapterAddresses; - ULONG address_len; - my_bool return_val= 1; - static pfnGetAdaptersAddresses fnGetAdaptersAddresses= - (pfnGetAdaptersAddresses)-1; - - if(fnGetAdaptersAddresses == (pfnGetAdaptersAddresses)-1) - { - /* Get the function from the DLL */ - fnGetAdaptersAddresses= (pfnGetAdaptersAddresses) - GetProcAddress(LoadLibrary("iphlpapi.dll"), - "GetAdaptersAddresses"); - } - if (!fnGetAdaptersAddresses) - return 1; /* failed to get function */ - address_len= sizeof (IP_ADAPTER_ADDRESSES); - - /* Get the required size for the address data. */ - if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, &adapterAddresses, &address_len) - == ERROR_BUFFER_OVERFLOW) - { - pAdapterAddresses= my_malloc(address_len, 0); - if (!pAdapterAddresses) - return 1; /* error, alloc failed */ - } - else - pAdapterAddresses= &adapterAddresses; /* one is enough don't alloc */ - - /* Get the hardware info. */ - if (fnGetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &address_len) - == NO_ERROR) - { - pCurrAddresses= pAdapterAddresses; - - while (pCurrAddresses) - { - /* Look for ethernet cards. */ - if (pCurrAddresses->IfType == IF_TYPE_ETHERNET_CSMACD) - { - /* check for a good address */ - if (pCurrAddresses->PhysicalAddressLength < 6) - continue; /* bad address */ - - /* save 6 bytes of the address in the 'to' parameter */ - memcpy(to, pCurrAddresses->PhysicalAddress, 6); - - /* Network card found, we're done. */ - return_val= 0; - break; - } - pCurrAddresses= pCurrAddresses->Next; - } - } - - /* Clean up memory allocation. */ - if (pAdapterAddresses != &adapterAddresses) - my_free(pAdapterAddresses); - - return return_val; -} - -#else /* __FreeBSD__ || __linux__ || __WIN__ */ -/* just fail */ -my_bool my_gethwaddr(uchar *to __attribute__((unused))) -{ - return 1; -} -#endif - -#else /* MAIN */ -int main(int argc __attribute__((unused)),char **argv) -{ - uchar mac[6]; - uint i; - MY_INIT(argv[0]); - if (my_gethwaddr(mac)) - { - printf("my_gethwaddr failed with errno %d\n", errno); - exit(1); - } - for (i=0; i < sizeof(mac); i++) - { - if (i) printf(":"); - printf("%02x", mac[i]); - } - printf("\n"); - return 0; -} -#endif - diff --git a/dep/mysqllite/mysys/my_getncpus.c b/dep/mysqllite/mysys/my_getncpus.c deleted file mode 100644 index 5be961e3bc9..00000000000 --- a/dep/mysqllite/mysys/my_getncpus.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (C) 2006 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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" -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -static int ncpus=0; - -int my_getncpus() -{ - if (!ncpus) - { -#ifdef _SC_NPROCESSORS_ONLN - ncpus= sysconf(_SC_NPROCESSORS_ONLN); -#elif defined(__WIN__) - SYSTEM_INFO sysinfo; - - /* - * We are not calling GetNativeSystemInfo here because (1) we - * don't believe that they return different values for number - * of processors and (2) if WOW64 limits processors for Win32 - * then we don't want to try to override that. - */ - GetSystemInfo(&sysinfo); - - ncpus= sysinfo.dwNumberOfProcessors; -#else -/* unknown so play safe: assume SMP and forbid uniprocessor build */ - ncpus= 2; -#endif - } - return ncpus; -} diff --git a/dep/mysqllite/mysys/my_getopt.c b/dep/mysqllite/mysys/my_getopt.c deleted file mode 100644 index 51c45ff1309..00000000000 --- a/dep/mysqllite/mysys/my_getopt.c +++ /dev/null @@ -1,1419 +0,0 @@ -/* Copyright (C) 2002-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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> -#include <stdlib.h> -#include <my_sys.h> -#include <mysys_err.h> -#include <my_getopt.h> -#include <errno.h> -#include <m_string.h> - -typedef void (*init_func_p)(const struct my_option *option, void *variable, - longlong value); - -static void default_reporter(enum loglevel level, const char *format, ...); -my_error_reporter my_getopt_error_reporter= &default_reporter; - -static int findopt(char *, uint, const struct my_option **, const char **); -my_bool getopt_compare_strings(const char *, const char *, uint); -static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); -static ulonglong getopt_ull(char *, const struct my_option *, int *); -static double getopt_double(char *arg, const struct my_option *optp, int *err); -static void init_variables(const struct my_option *, init_func_p); -static void init_one_value(const struct my_option *, void *, longlong); -static void fini_one_value(const struct my_option *, void *, longlong); -static int setval(const struct my_option *, void *, char *, my_bool); -static char *check_struct_option(char *cur_arg, char *key_name); - -/* - The following three variables belong to same group and the number and - order of their arguments must correspond to each other. -*/ -static const char *special_opt_prefix[]= -{"skip", "disable", "enable", "maximum", "loose", 0}; -static const uint special_opt_prefix_lengths[]= -{ 4, 7, 6, 7, 5, 0}; -enum enum_special_opt -{ OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE}; - -char *disabled_my_option= (char*) "0"; -char *enabled_my_option= (char*) "1"; - -/* - This is a flag that can be set in client programs. 0 means that - my_getopt will not print error messages, but the client should do - it by itself -*/ - -my_bool my_getopt_print_errors= 1; - -/* - This is a flag that can be set in client programs. 1 means that - my_getopt will skip over options it does not know how to handle. -*/ - -my_bool my_getopt_skip_unknown= 0; - -static void default_reporter(enum loglevel level, - const char *format, ...) -{ - va_list args; - va_start(args, format); - if (level == WARNING_LEVEL) - fprintf(stderr, "%s", "Warning: "); - else if (level == INFORMATION_LEVEL) - fprintf(stderr, "%s", "Info: "); - vfprintf(stderr, format, args); - va_end(args); - fputc('\n', stderr); - fflush(stderr); -} - -static my_getopt_value getopt_get_addr; - -void my_getopt_register_get_addr(my_getopt_value func_addr) -{ - getopt_get_addr= func_addr; -} - -/** - Handle command line options. - Sort options. - Put options first, until special end of options (--), - or until the end of argv. Parse options, check that the given option - matches with one of the options in struct 'my_option'. - Check that option was given an argument if it requires one - Call the optional 'get_one_option()' function once for each option. - - Note that handle_options() can be invoked multiple times to - parse a command line in several steps. - In this case, use the global flag @c my_getopt_skip_unknown to indicate - that options unknown in the current step should be preserved in the - command line for later parsing in subsequent steps. - - For 'long' options (--a_long_option), @c my_getopt_skip_unknown is - fully supported. Command line parameters such as: - - "--a_long_option" - - "--a_long_option=value" - - "--a_long_option value" - will be preserved as is when the option is not known. - - For 'short' options (-S), support for @c my_getopt_skip_unknown - comes with some limitation, because several short options - can also be specified together in the same command line argument, - as in "-XYZ". - - The first use case supported is: all short options are declared. - handle_options() will be able to interpret "-XYZ" as one of: - - an unknown X option - - "-X -Y -Z", three short options with no arguments - - "-X -YZ", where Y is a short option with argument Z - - "-XYZ", where X is a short option with argument YZ - based on the full short options specifications. - - The second use case supported is: no short option is declared. - handle_options() will reject "-XYZ" as unknown, to be parsed later. - - The use case that is explicitly not supported is to provide - only a partial list of short options to handle_options(). - This function can not be expected to extract some option Y - in the middle of the string "-XYZ" in these conditions, - without knowing if X will be declared an option later. - - Note that this limitation only impacts parsing of several - short options from the same command line argument, - as in "mysqld -anW5". - When each short option is properly separated out in the command line - argument, for example in "mysqld -a -n -w5", the code would actually - work even with partial options specs given at each stage. - - @param [in, out] argc command line options (count) - @param [in, out] argv command line options (values) - @param [in] longopts descriptor of all valid options - @param [in] get_one_option optional callback function to process each option, - can be NULL. - @return error in case of ambiguous or unknown options, - 0 on success. -*/ -int handle_options(int *argc, char ***argv, - const struct my_option *longopts, - my_get_one_option get_one_option) -{ - uint UNINIT_VAR(opt_found), argvpos= 0, length; - my_bool end_of_options= 0, must_be_var, set_maximum_value, - option_is_loose; - char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN]; - const char *UNINIT_VAR(prev_found); - const struct my_option *optp; - void *value; - int error, i; - my_bool is_cmdline_arg= 1; - - /* handle_options() assumes arg0 (program name) always exists */ - DBUG_ASSERT(argc && *argc >= 1); - DBUG_ASSERT(argv && *argv); - (*argc)--; /* Skip the program name */ - (*argv)++; /* --- || ---- */ - init_variables(longopts, init_one_value); - - /* - Search for args_separator, if found, then the first part of the - arguments are loaded from configs - */ - for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) - { - if (*pos == args_separator) - { - is_cmdline_arg= 0; - break; - } - } - - for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++) - { - char **first= pos; - char *cur_arg= *pos; - opt_found= 0; - if (!is_cmdline_arg && (cur_arg == args_separator)) - { - is_cmdline_arg= 1; - - /* save the separator too if skip unkown options */ - if (my_getopt_skip_unknown) - (*argv)[argvpos++]= cur_arg; - else - (*argc)--; - continue; - } - if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */ - { - char *argument= 0; - must_be_var= 0; - set_maximum_value= 0; - option_is_loose= 0; - - cur_arg++; /* skip '-' */ - if (*cur_arg == '-') /* check for long option, */ - { - if (!*++cur_arg) /* skip the double dash */ - { - /* '--' means end of options, look no further */ - end_of_options= 1; - (*argc)--; - continue; - } - opt_str= check_struct_option(cur_arg, key_name); - optend= strcend(opt_str, '='); - length= (uint) (optend - opt_str); - if (*optend == '=') - optend++; - else - optend= 0; - - /* - Find first the right option. Return error in case of an ambiguous, - or unknown option - */ - optp= longopts; - if (!(opt_found= findopt(opt_str, length, &optp, &prev_found))) - { - /* - Didn't find any matching option. Let's see if someone called - option with a special option prefix - */ - if (!must_be_var) - { - if (optend) - must_be_var= 1; /* option is followed by an argument */ - for (i= 0; special_opt_prefix[i]; i++) - { - if (!getopt_compare_strings(special_opt_prefix[i], opt_str, - special_opt_prefix_lengths[i]) && - (opt_str[special_opt_prefix_lengths[i]] == '-' || - opt_str[special_opt_prefix_lengths[i]] == '_')) - { - /* - We were called with a special prefix, we can reuse opt_found - */ - opt_str+= special_opt_prefix_lengths[i] + 1; - length-= special_opt_prefix_lengths[i] + 1; - if (i == OPT_LOOSE) - option_is_loose= 1; - if ((opt_found= findopt(opt_str, length, &optp, &prev_found))) - { - if (opt_found > 1) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: ambiguous option '--%s-%s' (--%s-%s)", - my_progname, special_opt_prefix[i], - opt_str, special_opt_prefix[i], - prev_found); - return EXIT_AMBIGUOUS_OPTION; - } - switch (i) { - case OPT_SKIP: - case OPT_DISABLE: /* fall through */ - /* - double negation is actually enable again, - for example: --skip-option=0 -> option = TRUE - */ - optend= (optend && *optend == '0' && !(*(optend + 1))) ? - enabled_my_option : disabled_my_option; - break; - case OPT_ENABLE: - optend= (optend && *optend == '0' && !(*(optend + 1))) ? - disabled_my_option : enabled_my_option; - break; - case OPT_MAXIMUM: - set_maximum_value= 1; - must_be_var= 1; - break; - } - break; /* break from the inner loop, main loop continues */ - } - i= -1; /* restart the loop */ - } - } - } - if (!opt_found) - { - if (my_getopt_skip_unknown) - { - /* Preserve all the components of this unknown option. */ - do { - (*argv)[argvpos++]= *first++; - } while (first <= pos); - continue; - } - if (must_be_var) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(option_is_loose ? - WARNING_LEVEL : ERROR_LEVEL, - "%s: unknown variable '%s'", - my_progname, cur_arg); - if (!option_is_loose) - return EXIT_UNKNOWN_VARIABLE; - } - else - { - if (my_getopt_print_errors) - my_getopt_error_reporter(option_is_loose ? - WARNING_LEVEL : ERROR_LEVEL, - "%s: unknown option '--%s'", - my_progname, cur_arg); - if (!option_is_loose) - return EXIT_UNKNOWN_OPTION; - } - if (option_is_loose) - { - (*argc)--; - continue; - } - } - } - if (opt_found > 1) - { - if (must_be_var) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: variable prefix '%s' is not unique", - my_progname, opt_str); - return EXIT_VAR_PREFIX_NOT_UNIQUE; - } - else - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: ambiguous option '--%s' (%s, %s)", - my_progname, opt_str, prev_found, - optp->name); - return EXIT_AMBIGUOUS_OPTION; - } - } - if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED) - { - if (my_getopt_print_errors) - fprintf(stderr, - "%s: %s: Option '%s' used, but is disabled\n", my_progname, - option_is_loose ? "WARNING" : "ERROR", opt_str); - if (option_is_loose) - { - (*argc)--; - continue; - } - return EXIT_OPTION_DISABLED; - } - error= 0; - value= optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) : - optp->value; - if (error) - return error; - - if (optp->arg_type == NO_ARG) - { - /* - Due to historical reasons GET_BOOL var_types still accepts arguments - despite the NO_ARG arg_type attribute. This can seems a bit unintuitive - and care should be taken when refactoring this code. - */ - if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: option '--%s' cannot take an argument", - my_progname, optp->name); - return EXIT_NO_ARGUMENT_ALLOWED; - } - if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) - { - /* - Set bool to 1 if no argument or if the user has used - --enable-'option-name'. - *optend was set to '0' if one used --disable-option - */ - (*argc)--; - if (!optend || *optend == '1' || - !my_strcasecmp(&my_charset_latin1, optend, "true")) - *((my_bool*) value)= (my_bool) 1; - else if (*optend == '0' || - !my_strcasecmp(&my_charset_latin1, optend, "false")) - *((my_bool*) value)= (my_bool) 0; - else - { - my_getopt_error_reporter(WARNING_LEVEL, - "%s: ignoring option '--%s' " - "due to invalid value '%s'", - my_progname, optp->name, optend); - continue; - } - if (get_one_option && get_one_option(optp->id, optp, - *((my_bool*) value) ? - enabled_my_option : disabled_my_option)) - return EXIT_ARGUMENT_INVALID; - continue; - } - argument= optend; - } - else if (optp->arg_type == REQUIRED_ARG && !optend) - { - /* Check if there are more arguments after this one, - Note: options loaded from config file that requires value - should always be in the form '--option=value'. - */ - if (!is_cmdline_arg || !*++pos) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: option '--%s' requires an argument", - my_progname, optp->name); - return EXIT_ARGUMENT_REQUIRED; - } - argument= *pos; - (*argc)--; - } - else - argument= optend; - } - else /* must be short option */ - { - for (optend= cur_arg; *optend; optend++) - { - opt_found= 0; - for (optp= longopts; optp->name; optp++) - { - if (optp->id && optp->id == (int) (uchar) *optend) - { - /* Option recognized. Find next what to do with it */ - opt_found= 1; - if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED) - { - if (my_getopt_print_errors) - fprintf(stderr, - "%s: ERROR: Option '-%c' used, but is disabled\n", - my_progname, optp->id); - return EXIT_OPTION_DISABLED; - } - if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL && - optp->arg_type == NO_ARG) - { - *((my_bool*) optp->value)= (my_bool) 1; - if (get_one_option && get_one_option(optp->id, optp, argument)) - return EXIT_UNSPECIFIED_ERROR; - continue; - } - else if (optp->arg_type == REQUIRED_ARG || - optp->arg_type == OPT_ARG) - { - if (*(optend + 1)) - { - /* The rest of the option is option argument */ - argument= optend + 1; - /* This is in effect a jump out of the outer loop */ - optend= (char*) " "; - } - else - { - if (optp->arg_type == OPT_ARG) - { - if (optp->var_type == GET_BOOL) - *((my_bool*) optp->value)= (my_bool) 1; - if (get_one_option && get_one_option(optp->id, optp, argument)) - return EXIT_UNSPECIFIED_ERROR; - continue; - } - /* Check if there are more arguments after this one */ - if (!pos[1]) - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: option '-%c' requires an argument", - my_progname, optp->id); - return EXIT_ARGUMENT_REQUIRED; - } - argument= *++pos; - (*argc)--; - /* the other loop will break, because *optend + 1 == 0 */ - } - } - if ((error= setval(optp, optp->value, argument, - set_maximum_value))) - return error; - if (get_one_option && get_one_option(optp->id, optp, argument)) - return EXIT_UNSPECIFIED_ERROR; - break; - } - } - if (!opt_found) - { - if (my_getopt_skip_unknown) - { - /* - We are currently parsing a single argv[] argument - of the form "-XYZ". - One or the argument found (say Y) is not an option. - Hack the string "-XYZ" to make a "-YZ" substring in it, - and push that to the output as an unrecognized parameter. - */ - DBUG_ASSERT(optend > *pos); - DBUG_ASSERT(optend >= cur_arg); - DBUG_ASSERT(optend <= *pos + strlen(*pos)); - DBUG_ASSERT(*optend); - optend--; - optend[0]= '-'; /* replace 'X' or '-' by '-' */ - (*argv)[argvpos++]= optend; - /* - Do not continue to parse at the current "-XYZ" argument, - skip to the next argv[] argument instead. - */ - optend= (char*) " "; - } - else - { - if (my_getopt_print_errors) - my_getopt_error_reporter(ERROR_LEVEL, - "%s: unknown option '-%c'", - my_progname, *optend); - return EXIT_UNKNOWN_OPTION; - } - } - } - if (opt_found) - (*argc)--; /* option handled (short), decrease argument count */ - continue; - } - if ((error= setval(optp, value, argument, set_maximum_value))) - return error; - if (get_one_option && get_one_option(optp->id, optp, argument)) - return EXIT_UNSPECIFIED_ERROR; - - (*argc)--; /* option handled (long), decrease argument count */ - } - else /* non-option found */ - (*argv)[argvpos++]= cur_arg; - } - /* - Destroy the first, already handled option, so that programs that look - for arguments in 'argv', without checking 'argc', know when to stop. - Items in argv, before the destroyed one, are all non-option -arguments - to the program, yet to be (possibly) handled. - */ - (*argv)[argvpos]= 0; - return 0; -} - - -/* - function: check_struct_option - - Arguments: Current argument under processing from argv and a variable - where to store the possible key name. - - Return value: In case option is a struct option, returns a pointer to - the current argument at the position where the struct option (key_name) - ends, the next character after the dot. In case argument is not a struct - option, returns a pointer to the argument. - - key_name will hold the name of the key, or 0 if not found. -*/ - -static char *check_struct_option(char *cur_arg, char *key_name) -{ - char *ptr, *end; - - ptr= strcend(cur_arg + 1, '.'); /* Skip the first character */ - end= strcend(cur_arg, '='); - - /* - If the first dot is after an equal sign, then it is part - of a variable value and the option is not a struct option. - Also, if the last character in the string before the ending - NULL, or the character right before equal sign is the first - dot found, the option is not a struct option. - */ - if (end - ptr > 1) - { - uint len= (uint) (ptr - cur_arg); - set_if_smaller(len, FN_REFLEN-1); - strmake(key_name, cur_arg, len); - return ++ptr; - } - else - { - key_name[0]= 0; - return cur_arg; - } -} - -/** - Parse a boolean command line argument - - "ON", "TRUE" and "1" will return true, - other values will return false. - - @param[in] argument The value argument - @return boolean value -*/ -static my_bool get_bool_argument(const char *argument) -{ - if (!my_strcasecmp(&my_charset_latin1, argument, "true") || - !my_strcasecmp(&my_charset_latin1, argument, "on")) - return 1; - else - return (my_bool) atoi(argument); -} - -/* - function: setval - - Arguments: opts, argument - Will set the option value to given value -*/ - -static int setval(const struct my_option *opts, void *value, char *argument, - my_bool set_maximum_value) -{ - int err= 0, res= 0; - - if (!argument) - argument= enabled_my_option; - - if (value) - { - if (set_maximum_value && !(value= opts->u_max_value)) - { - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Maximum value of '%s' cannot be set", - my_progname, opts->name); - return EXIT_NO_PTR_TO_VARIABLE; - } - - switch ((opts->var_type & GET_TYPE_MASK)) { - case GET_BOOL: /* If argument differs from 0, enable option, else disable */ - *((my_bool*) value)= get_bool_argument(argument); - break; - case GET_INT: - *((int*) value)= (int) getopt_ll(argument, opts, &err); - break; - case GET_UINT: - *((uint*) value)= (uint) getopt_ull(argument, opts, &err); - break; - case GET_LONG: - *((long*) value)= (long) getopt_ll(argument, opts, &err); - break; - case GET_ULONG: - *((long*) value)= (long) getopt_ull(argument, opts, &err); - break; - case GET_LL: - *((longlong*) value)= getopt_ll(argument, opts, &err); - break; - case GET_ULL: - *((ulonglong*) value)= getopt_ull(argument, opts, &err); - break; - case GET_DOUBLE: - *((double*) value)= getopt_double(argument, opts, &err); - break; - case GET_STR: - if (argument == enabled_my_option) - break; /* string options don't use this default of "1" */ - *((char**) value)= argument; - break; - case GET_STR_ALLOC: - if (argument == enabled_my_option) - break; /* string options don't use this default of "1" */ - my_free(*((char**) value)); - if (!(*((char**) value)= my_strdup(argument, MYF(MY_WME)))) - { - res= EXIT_OUT_OF_MEMORY; - goto ret; - }; - break; - case GET_ENUM: - { - int type= find_type(argument, opts->typelib, 2); - if (type == 0) - { - /* - Accept an integer representation of the enumerated item. - */ - char *endptr; - ulong arg= strtoul(argument, &endptr, 10); - if (*endptr || arg >= opts->typelib->count) - { - res= EXIT_ARGUMENT_INVALID; - goto ret; - } - *(ulong*)value= arg; - } - else - *(ulong*)value= type - 1; - } - break; - case GET_SET: - *((ulonglong*)value)= find_typeset(argument, opts->typelib, &err); - if (err) - { - /* Accept an integer representation of the set */ - char *endptr; - ulonglong arg= (ulonglong) strtol(argument, &endptr, 10); - if (*endptr || (arg >> 1) >= (1ULL << (opts->typelib->count-1))) - { - res= EXIT_ARGUMENT_INVALID; - goto ret; - }; - *(ulonglong*)value= arg; - err= 0; - } - break; - case GET_FLAGSET: - { - char *error; - uint error_len; - - *((ulonglong*)value)= - find_set_from_flags(opts->typelib, opts->typelib->count, - *(ulonglong *)value, opts->def_value, - argument, strlen(argument), - &error, &error_len); - if (error) - { - res= EXIT_ARGUMENT_INVALID; - goto ret; - }; - } - break; - case GET_NO_ARG: /* get_one_option has taken care of the value already */ - default: /* dummy default to avoid compiler warnings */ - break; - } - if (err) - { - res= EXIT_UNKNOWN_SUFFIX; - goto ret; - }; - } - return 0; - -ret: - my_getopt_error_reporter(ERROR_LEVEL, - "%s: Error while setting value '%s' to '%s'", - my_progname, argument, opts->name); - return res; -} - - -/* - Find option - - SYNOPSIS - findopt() - optpat Prefix of option to find (with - or _) - length Length of optpat - opt_res Options - ffname Place for pointer to first found name - - IMPLEMENTATION - Go through all options in the my_option struct. Return number - of options found that match the pattern and in the argument - list the option found, if any. In case of ambiguous option, store - the name in ffname argument - - RETURN - 0 No matching options - # Number of matching options - ffname points to first matching option -*/ - -static int findopt(char *optpat, uint length, - const struct my_option **opt_res, - const char **ffname) -{ - uint count; - const struct my_option *opt= *opt_res; - - for (count= 0; opt->name; opt++) - { - if (!getopt_compare_strings(opt->name, optpat, length)) /* match found */ - { - (*opt_res)= opt; - if (!opt->name[length]) /* Exact match */ - return 1; - if (!count) - { - /* We only need to know one prev */ - count= 1; - *ffname= opt->name; - } - else if (strcmp(*ffname, opt->name)) - { - /* - The above test is to not count same option twice - (see mysql.cc, option "help") - */ - count++; - } - } - } - return count; -} - - -/* - function: compare_strings - - Works like strncmp, other than 1.) considers '-' and '_' the same. - 2.) Returns -1 if strings differ, 0 if they are equal -*/ - -my_bool getopt_compare_strings(register const char *s, register const char *t, - uint length) -{ - char const *end= s + length; - for (;s != end ; s++, t++) - { - if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_')) - return 1; - } - return 0; -} - -/* - function: eval_num_suffix - - Transforms a number with a suffix to real number. Suffix can - be k|K for kilo, m|M for mega or g|G for giga. -*/ - -static longlong eval_num_suffix(char *argument, int *error, char *option_name) -{ - char *endchar; - longlong num; - - *error= 0; - errno= 0; - num= strtoll(argument, &endchar, 10); - if (errno == ERANGE) - { - my_getopt_error_reporter(ERROR_LEVEL, - "Incorrect integer value: '%s'", argument); - *error= 1; - return 0; - } - if (*endchar == 'k' || *endchar == 'K') - num*= 1024L; - else if (*endchar == 'm' || *endchar == 'M') - num*= 1024L * 1024L; - else if (*endchar == 'g' || *endchar == 'G') - num*= 1024L * 1024L * 1024L; - else if (*endchar) - { - fprintf(stderr, - "Unknown suffix '%c' used for variable '%s' (value '%s')\n", - *endchar, option_name, argument); - *error= 1; - return 0; - } - return num; -} - -/* - function: getopt_ll - - Evaluates and returns the value that user gave as an argument - to a variable. Recognizes (case insensitive) K as KILO, M as MEGA - and G as GIGA bytes. Some values must be in certain blocks, as - defined in the given my_option struct, this function will check - that those values are honored. - In case of an error, set error value in *err. -*/ - -static longlong getopt_ll(char *arg, const struct my_option *optp, int *err) -{ - longlong num=eval_num_suffix(arg, err, (char*) optp->name); - return getopt_ll_limit_value(num, optp, NULL); -} - -/* - function: getopt_ll_limit_value - - Applies min/max/block_size to a numeric value of an option. - Returns "fixed" value. -*/ - -longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, - my_bool *fix) -{ - longlong old= num; - my_bool adjusted= FALSE; - char buf1[255], buf2[255]; - ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L); - - if (num > 0 && ((ulonglong) num > (ulonglong) optp->max_value) && - optp->max_value) /* if max value is not set -> no upper limit */ - { - num= (ulonglong) optp->max_value; - adjusted= TRUE; - } - - switch ((optp->var_type & GET_TYPE_MASK)) { - case GET_INT: - if (num > (longlong) INT_MAX) - { - num= ((longlong) INT_MAX); - adjusted= TRUE; - } - break; - case GET_LONG: -#if SIZEOF_LONG < SIZEOF_LONG_LONG - if (num > (longlong) LONG_MAX) - { - num= ((longlong) LONG_MAX); - adjusted= TRUE; - } -#endif - break; - default: - DBUG_ASSERT((optp->var_type & GET_TYPE_MASK) == GET_LL); - break; - } - - num= (num / block_size); - num= (longlong) (num * block_size); - - if (num < optp->min_value) - { - num= optp->min_value; - if (old < optp->min_value) - adjusted= TRUE; - } - - if (fix) - *fix= old != num; - else if (adjusted) - my_getopt_error_reporter(WARNING_LEVEL, - "option '%s': signed value %s adjusted to %s", - optp->name, llstr(old, buf1), llstr(num, buf2)); - return num; -} - -/* - function: getopt_ull - - This is the same as getopt_ll, but is meant for unsigned long long - values. -*/ - -static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err) -{ - ulonglong num= eval_num_suffix(arg, err, (char*) optp->name); - return getopt_ull_limit_value(num, optp, NULL); -} - - -ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp, - my_bool *fix) -{ - my_bool adjusted= FALSE; - ulonglong old= num; - char buf1[255], buf2[255]; - - if ((ulonglong) num > (ulonglong) optp->max_value && - optp->max_value) /* if max value is not set -> no upper limit */ - { - num= (ulonglong) optp->max_value; - adjusted= TRUE; - } - - switch ((optp->var_type & GET_TYPE_MASK)) { - case GET_UINT: - if (num > (ulonglong) UINT_MAX) - { - num= ((ulonglong) UINT_MAX); - adjusted= TRUE; - } - break; - case GET_ULONG: -#if SIZEOF_LONG < SIZEOF_LONG_LONG - if (num > (ulonglong) ULONG_MAX) - { - num= ((ulonglong) ULONG_MAX); - adjusted= TRUE; - } -#endif - break; - default: - DBUG_ASSERT((optp->var_type & GET_TYPE_MASK) == GET_ULL); - break; - } - - if (optp->block_size > 1) - { - num/= (ulonglong) optp->block_size; - num*= (ulonglong) optp->block_size; - } - - if (num < (ulonglong) optp->min_value) - { - num= (ulonglong) optp->min_value; - if (old < (ulonglong) optp->min_value) - adjusted= TRUE; - } - - if (fix) - *fix= old != num; - else if (adjusted) - my_getopt_error_reporter(WARNING_LEVEL, - "option '%s': unsigned value %s adjusted to %s", - optp->name, ullstr(old, buf1), ullstr(num, buf2)); - - return num; -} - -double getopt_double_limit_value(double num, const struct my_option *optp, - my_bool *fix) -{ - my_bool adjusted= FALSE; - double old= num; - if (optp->max_value && num > (double) optp->max_value) - { - num= (double) optp->max_value; - adjusted= TRUE; - } - if (num < (double) optp->min_value) - { - num= (double) optp->min_value; - adjusted= TRUE; - } - if (fix) - *fix= adjusted; - else if (adjusted) - my_getopt_error_reporter(WARNING_LEVEL, - "option '%s': value %g adjusted to %g", - optp->name, old, num); - return num; -} - -/* - Get double value withing ranges - - Evaluates and returns the value that user gave as an argument to a variable. - - RETURN - decimal value of arg - - In case of an error, prints an error message and sets *err to - EXIT_ARGUMENT_INVALID. Otherwise err is not touched -*/ - -static double getopt_double(char *arg, const struct my_option *optp, int *err) -{ - double num; - int error; - char *end= arg + 1000; /* Big enough as *arg is \0 terminated */ - num= my_strtod(arg, &end, &error); - if (end[0] != 0 || error) - { - my_getopt_error_reporter(ERROR_LEVEL, - "Invalid decimal value for option '%s'\n", optp->name); - *err= EXIT_ARGUMENT_INVALID; - return 0.0; - } - return getopt_double_limit_value(num, optp, NULL); -} - -/* - Init one value to it's default values - - SYNOPSIS - init_one_value() - option Option to initialize - value Pointer to variable -*/ - -static void init_one_value(const struct my_option *option, void *variable, - longlong value) -{ - DBUG_ENTER("init_one_value"); - switch ((option->var_type & GET_TYPE_MASK)) { - case GET_BOOL: - *((my_bool*) variable)= (my_bool) value; - break; - case GET_INT: - *((int*) variable)= (int) getopt_ll_limit_value((int) value, option, NULL); - break; - case GET_ENUM: - *((ulong*) variable)= (ulong) value; - break; - case GET_UINT: - *((uint*) variable)= (uint) getopt_ull_limit_value((uint) value, option, NULL); - break; - case GET_LONG: - *((long*) variable)= (long) getopt_ll_limit_value((long) value, option, NULL); - break; - case GET_ULONG: - *((ulong*) variable)= (ulong) getopt_ull_limit_value((ulong) value, option, NULL); - break; - case GET_LL: - *((longlong*) variable)= (longlong) getopt_ll_limit_value((longlong) value, option, NULL); - break; - case GET_ULL: - *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL); - break; - case GET_SET: - case GET_FLAGSET: - *((ulonglong*) variable)= (ulonglong) value; - break; - case GET_DOUBLE: - *((double*) variable)= ulonglong2double(value); - break; - case GET_STR: - /* - Do not clear variable value if it has no default value. - The default value may already be set. - NOTE: To avoid compiler warnings, we first cast longlong to intptr, - so that the value has the same size as a pointer. - */ - if ((char*) (intptr) value) - *((char**) variable)= (char*) (intptr) value; - break; - case GET_STR_ALLOC: - /* - Do not clear variable value if it has no default value. - The default value may already be set. - NOTE: To avoid compiler warnings, we first cast longlong to intptr, - so that the value has the same size as a pointer. - */ - if ((char*) (intptr) value) - { - char **pstr= (char **) variable; - my_free(*pstr); - *pstr= my_strdup((char*) (intptr) value, MYF(MY_WME)); - } - break; - default: /* dummy default to avoid compiler warnings */ - break; - } - DBUG_VOID_RETURN; -} - - -/* - Init one value to it's default values - - SYNOPSIS - init_one_value() - option Option to initialize - value Pointer to variable -*/ - -static void fini_one_value(const struct my_option *option, void *variable, - longlong value __attribute__ ((unused))) -{ - DBUG_ENTER("fini_one_value"); - switch ((option->var_type & GET_TYPE_MASK)) { - case GET_STR_ALLOC: - my_free(*((char**) variable)); - *((char**) variable)= NULL; - break; - default: /* dummy default to avoid compiler warnings */ - break; - } - DBUG_VOID_RETURN; -} - - -void my_cleanup_options(const struct my_option *options) -{ - init_variables(options, fini_one_value); -} - - -/* - initialize all variables to their default values - - SYNOPSIS - init_variables() - options Array of options - - NOTES - We will initialize the value that is pointed to by options->value. - If the value is of type GET_ASK_ADDR, we will ask for the address - for a value and initialize. -*/ - -static void init_variables(const struct my_option *options, - init_func_p init_one_value) -{ - DBUG_ENTER("init_variables"); - for (; options->name; options++) - { - void *value; - DBUG_PRINT("options", ("name: '%s'", options->name)); - /* - We must set u_max_value first as for some variables - options->u_max_value == options->value and in this case we want to - set the value to default value. - */ - if (options->u_max_value) - init_one_value(options, options->u_max_value, options->max_value); - value= (options->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)("", 0, options, 0) : options->value); - if (value) - init_one_value(options, value, options->def_value); - } - DBUG_VOID_RETURN; -} - -/** Prints variable or option name, replacing _ with - */ -static uint print_name(const struct my_option *optp) -{ - const char *s= optp->name; - for (;*s;s++) - putchar(*s == '_' ? '-' : *s); - return s - optp->name; -} - -/* - function: my_print_options - - Print help for all options and variables. -*/ - -void my_print_help(const struct my_option *options) -{ - uint col, name_space= 22, comment_space= 57; - const char *line_end; - const struct my_option *optp; - - for (optp= options; optp->name; optp++) - { - if (optp->id && optp->id < 256) - { - printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " "); - col= 6; - } - else - { - printf(" "); - col= 2; - } - if (strlen(optp->name)) - { - printf("--"); - col+= 2 + print_name(optp); - if (optp->arg_type == NO_ARG || - (optp->var_type & GET_TYPE_MASK) == GET_BOOL) - { - putchar(' '); - col++; - } - else if ((optp->var_type & GET_TYPE_MASK) == GET_STR || - (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC || - (optp->var_type & GET_TYPE_MASK) == GET_ENUM || - (optp->var_type & GET_TYPE_MASK) == GET_SET || - (optp->var_type & GET_TYPE_MASK) == GET_FLAGSET ) - { - printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "", - optp->arg_type == OPT_ARG ? "]" : ""); - col+= (optp->arg_type == OPT_ARG) ? 8 : 6; - } - else - { - printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "", - optp->arg_type == OPT_ARG ? "]" : ""); - col+= (optp->arg_type == OPT_ARG) ? 5 : 3; - } - if (col > name_space && optp->comment && *optp->comment) - { - putchar('\n'); - col= 0; - } - } - for (; col < name_space; col++) - putchar(' '); - if (optp->comment && *optp->comment) - { - const char *comment= optp->comment, *end= strend(comment); - - while ((uint) (end - comment) > comment_space) - { - for (line_end= comment + comment_space; *line_end != ' '; line_end--); - for (; comment != line_end; comment++) - putchar(*comment); - comment++; /* skip the space, as a newline will take it's place now */ - putchar('\n'); - for (col= 0; col < name_space; col++) - putchar(' '); - } - printf("%s", comment); - } - putchar('\n'); - if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) - { - if (optp->def_value != 0) - { - printf("%*s(Defaults to on; use --skip-", name_space, ""); - print_name(optp); - printf(" to disable.)\n"); - } - } - } -} - - -/* - function: my_print_options - - Print variables. -*/ - -void my_print_variables(const struct my_option *options) -{ - uint name_space= 34, length, nr; - ulonglong llvalue; - char buff[255]; - const struct my_option *optp; - - for (optp= options; optp->name; optp++) - { - length= strlen(optp->name)+1; - if (length > name_space) - name_space= length; - } - - printf("\nVariables (--variable-name=value)\n"); - printf("%-*s%s", name_space, "and boolean options {FALSE|TRUE}", - "Value (after reading options)\n"); - for (length=1; length < 75; length++) - putchar(length == name_space ? ' ' : '-'); - putchar('\n'); - - for (optp= options; optp->name; optp++) - { - void *value= (optp->var_type & GET_ASK_ADDR ? - (*getopt_get_addr)("", 0, optp, 0) : optp->value); - if (value) - { - length= print_name(optp); - for (; length < name_space; length++) - putchar(' '); - switch ((optp->var_type & GET_TYPE_MASK)) { - case GET_SET: - if (!(llvalue= *(ulonglong*) value)) - printf("%s\n", ""); - else - for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1) - { - if (llvalue & 1) - printf( llvalue > 1 ? "%s," : "%s\n", get_type(optp->typelib, nr)); - } - break; - case GET_FLAGSET: - llvalue= *(ulonglong*) value; - for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1) - { - printf("%s%s=", (nr ? "," : ""), get_type(optp->typelib, nr)); - printf(llvalue & 1 ? "on" : "off"); - } - printf("\n"); - break; - case GET_ENUM: - printf("%s\n", get_type(optp->typelib, *(ulong*) value)); - break; - case GET_STR: - case GET_STR_ALLOC: /* fall through */ - printf("%s\n", *((char**) value) ? *((char**) value) : - "(No default value)"); - break; - case GET_BOOL: - printf("%s\n", *((my_bool*) value) ? "TRUE" : "FALSE"); - break; - case GET_INT: - printf("%d\n", *((int*) value)); - break; - case GET_UINT: - printf("%d\n", *((uint*) value)); - break; - case GET_LONG: - printf("%ld\n", *((long*) value)); - break; - case GET_ULONG: - printf("%lu\n", *((ulong*) value)); - break; - case GET_LL: - printf("%s\n", llstr(*((longlong*) value), buff)); - break; - case GET_ULL: - longlong2str(*((ulonglong*) value), buff, 10); - printf("%s\n", buff); - break; - case GET_DOUBLE: - printf("%g\n", *(double*) value); - break; - case GET_NO_ARG: - printf("(No default value)\n"); - break; - default: - printf("(Disabled)\n"); - break; - } - } - } -} diff --git a/dep/mysqllite/mysys/my_getpagesize.c b/dep/mysqllite/mysys/my_getpagesize.c deleted file mode 100644 index b0560cede35..00000000000 --- a/dep/mysqllite/mysys/my_getpagesize.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 2000-2003 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" - -#ifndef HAVE_GETPAGESIZE - -#if defined __WIN__ - -int my_getpagesize(void) -{ - SYSTEM_INFO si; - GetSystemInfo(&si); - return si.dwPageSize; -} - -#else - -/* Default implementation */ -int my_getpagesize(void) -{ - return (int)8192; -} - -#endif - -#endif - diff --git a/dep/mysqllite/mysys/my_getsystime.c b/dep/mysqllite/mysys/my_getsystime.c deleted file mode 100644 index 614f49fc425..00000000000 --- a/dep/mysqllite/mysys/my_getsystime.c +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 time since epoc in 100 nanosec units */ -/* thus to get the current time we should use the system function - with the highest possible resolution */ - -/* - TODO: in functions my_micro_time() and my_micro_time_and_time() there - exists some common code that should be merged into a function. -*/ - -#include "mysys_priv.h" -#include "my_static.h" - -ulonglong my_getsystime() -{ -#ifdef HAVE_CLOCK_GETTIME - struct timespec tp; - clock_gettime(CLOCK_REALTIME, &tp); - return (ulonglong)tp.tv_sec*10000000+(ulonglong)tp.tv_nsec/100; -#elif defined(__WIN__) - LARGE_INTEGER t_cnt; - if (query_performance_frequency) - { - QueryPerformanceCounter(&t_cnt); - return ((t_cnt.QuadPart / query_performance_frequency * 10000000) + - ((t_cnt.QuadPart % query_performance_frequency) * 10000000 / - query_performance_frequency) + query_performance_offset); - } - return 0; -#else - /* TODO: check for other possibilities for hi-res timestamping */ - struct timeval tv; - gettimeofday(&tv,NULL); - return (ulonglong)tv.tv_sec*10000000+(ulonglong)tv.tv_usec*10; -#endif -} - - -/* - Return current time - - SYNOPSIS - my_time() - flags If MY_WME is set, write error if time call fails - -*/ - -time_t my_time(myf flags __attribute__((unused))) -{ - time_t t; -#ifdef HAVE_GETHRTIME - (void) my_micro_time_and_time(&t); - return t; -#else - /* The following loop is here beacuse time() may fail on some systems */ - while ((t= time(0)) == (time_t) -1) - { - if (flags & MY_WME) - fprintf(stderr, "%s: Warning: time() call failed\n", my_progname); - } - return t; -#endif -} - - -/* - Return time in micro seconds - - SYNOPSIS - my_micro_time() - - NOTES - This function is to be used to measure performance in micro seconds. - As it's not defined whats the start time for the clock, this function - us only useful to measure time between two moments. - - For windows platforms we need the frequency value of the CUP. This is - initalized in my_init.c through QueryPerformanceFrequency(). - - If Windows platform doesn't support QueryPerformanceFrequency() we will - obtain the time via GetClockCount, which only supports milliseconds. - - RETURN - Value in microseconds from some undefined point in time -*/ - -ulonglong my_micro_time() -{ -#if defined(__WIN__) - ulonglong newtime; - GetSystemTimeAsFileTime((FILETIME*)&newtime); - return (newtime/10); -#elif defined(HAVE_GETHRTIME) - return gethrtime()/1000; -#else - ulonglong newtime; - struct timeval t; - /* - The following loop is here because gettimeofday may fail on some systems - */ - while (gettimeofday(&t, NULL) != 0) - {} - newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec; - return newtime; -#endif /* defined(__WIN__) */ -} - - -/* - Return time in seconds and timer in microseconds (not different start!) - - SYNOPSIS - my_micro_time_and_time() - time_arg Will be set to seconds since epoch (00:00:00 UTC, - January 1, 1970) - - NOTES - This function is to be useful when we need both the time and microtime. - For example in MySQL this is used to get the query time start of a query - and to measure the time of a query (for the slow query log) - - IMPLEMENTATION - Value of time is as in time() call. - Value of microtime is same as my_micro_time(), which may be totally - unrealated to time() - - RETURN - Value in microseconds from some undefined point in time -*/ - -#define DELTA_FOR_SECONDS 500000000LL /* Half a second */ - -/* Difference between GetSystemTimeAsFileTime() and now() */ -#define OFFSET_TO_EPOCH 116444736000000000ULL - -ulonglong my_micro_time_and_time(time_t *time_arg) -{ -#if defined(__WIN__) - ulonglong newtime; - GetSystemTimeAsFileTime((FILETIME*)&newtime); - *time_arg= (time_t) ((newtime - OFFSET_TO_EPOCH) / 10000000); - return (newtime/10); -#elif defined(HAVE_GETHRTIME) - /* - Solaris has a very slow time() call. We optimize this by using the very - fast gethrtime() call and only calling time() every 1/2 second - */ - static hrtime_t prev_gethrtime= 0; - static time_t cur_time= 0; - hrtime_t cur_gethrtime; - - mysql_mutex_lock(&THR_LOCK_time); - cur_gethrtime= gethrtime(); - /* - Due to bugs in the Solaris (x86) implementation of gethrtime(), - the time returned by it might not be monotonic. Don't use the - cached time(2) value if this is a case. - */ - if ((prev_gethrtime > cur_gethrtime) || - ((cur_gethrtime - prev_gethrtime) > DELTA_FOR_SECONDS)) - { - cur_time= time(0); - prev_gethrtime= cur_gethrtime; - } - *time_arg= cur_time; - mysql_mutex_unlock(&THR_LOCK_time); - return cur_gethrtime/1000; -#else - ulonglong newtime; - struct timeval t; - /* - The following loop is here because gettimeofday may fail on some systems - */ - while (gettimeofday(&t, NULL) != 0) - {} - *time_arg= t.tv_sec; - newtime= (ulonglong)t.tv_sec * 1000000 + t.tv_usec; - return newtime; -#endif /* defined(__WIN__) */ -} - - -/* - Returns current time - - SYNOPSIS - my_time_possible_from_micro() - microtime Value from very recent my_micro_time() - - NOTES - This function returns the current time. The microtime argument is only used - if my_micro_time() uses a function that can safely be converted to the - current time. - - RETURN - current time -*/ - -time_t my_time_possible_from_micro(ulonglong microtime __attribute__((unused))) -{ -#if defined(__WIN__) - time_t t; - while ((t= time(0)) == (time_t) -1) - {} - return t; -#elif defined(HAVE_GETHRTIME) - return my_time(0); /* Cached time */ -#else - return (time_t) (microtime / 1000000); -#endif /* defined(__WIN__) */ -} - diff --git a/dep/mysqllite/mysys/my_getwd.c b/dep/mysqllite/mysys/my_getwd.c deleted file mode 100644 index ace14c8a3c9..00000000000 --- a/dep/mysqllite/mysys/my_getwd.c +++ /dev/null @@ -1,167 +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 */ - -/* my_setwd() and my_getwd() works with intern_filenames !! */ - -#include "mysys_priv.h" -#include <m_string.h> -#include "mysys_err.h" -#ifdef HAVE_GETWD -#include <sys/param.h> -#endif -#if defined(__WIN__) -#include <m_ctype.h> -#include <dos.h> -#include <direct.h> -#endif - -/* Gets current working directory in buff. - - SYNPOSIS - my_getwd() - buf Buffer to store result. Can be curr_dir[]. - size Size of buffer - MyFlags Flags - - NOTES - Directory is allways ended with FN_LIBCHAR - - RESULT - 0 ok - # error -*/ - -int my_getwd(char * buf, size_t size, myf MyFlags) -{ - char * pos; - DBUG_ENTER("my_getwd"); - DBUG_PRINT("my",("buf: 0x%lx size: %u MyFlags %d", - (long) buf, (uint) size, MyFlags)); - - if (size < 1) - DBUG_RETURN(-1); - - if (curr_dir[0]) /* Current pos is saved here */ - (void) strmake(buf,&curr_dir[0],size-1); - else - { -#if defined(HAVE_GETCWD) - if (size < 2) - DBUG_RETURN(-1); - if (!getcwd(buf,(uint) (size-2)) && MyFlags & MY_WME) - { - my_errno=errno; - my_error(EE_GETWD,MYF(ME_BELL+ME_WAITTANG),errno); - DBUG_RETURN(-1); - } -#elif defined(HAVE_GETWD) - { - char pathname[MAXPATHLEN]; - getwd(pathname); - strmake(buf,pathname,size-1); - } -#else -#error "No way to get current directory" -#endif - if (*((pos=strend(buf))-1) != FN_LIBCHAR) /* End with FN_LIBCHAR */ - { - pos[0]= FN_LIBCHAR; - pos[1]=0; - } - (void) strmake(&curr_dir[0],buf, (size_t) (FN_REFLEN-1)); - } - DBUG_RETURN(0); -} /* my_getwd */ - - -/* Set new working directory */ - -int my_setwd(const char *dir, myf MyFlags) -{ - int res; - size_t length; - char *start, *pos; - DBUG_ENTER("my_setwd"); - DBUG_PRINT("my",("dir: '%s' MyFlags %d", dir, MyFlags)); - - start=(char *) dir; - if (! dir[0] || (dir[0] == FN_LIBCHAR && dir[1] == 0)) - dir=FN_ROOTDIR; - if ((res=chdir((char*) dir)) != 0) - { - my_errno=errno; - if (MyFlags & MY_WME) - my_error(EE_SETWD,MYF(ME_BELL+ME_WAITTANG),start,errno); - } - else - { - if (test_if_hard_path(start)) - { /* Hard pathname */ - pos= strmake(&curr_dir[0],start,(size_t) FN_REFLEN-1); - if (pos[-1] != FN_LIBCHAR) - { - length=(uint) (pos-(char*) curr_dir); - curr_dir[length]=FN_LIBCHAR; /* must end with '/' */ - curr_dir[length+1]='\0'; - } - } - else - curr_dir[0]='\0'; /* Don't save name */ - } - DBUG_RETURN(res); -} /* my_setwd */ - - - - /* Test if hard pathname */ - /* Returns 1 if dirname is a hard path */ - -int test_if_hard_path(register const char *dir_name) -{ - if (dir_name[0] == FN_HOMELIB && dir_name[1] == FN_LIBCHAR) - return (home_dir != NullS && test_if_hard_path(home_dir)); - if (dir_name[0] == FN_LIBCHAR) - return (TRUE); -#ifdef FN_DEVCHAR - return (strchr(dir_name,FN_DEVCHAR) != 0); -#else - return FALSE; -#endif -} /* test_if_hard_path */ - - -/* - Test if a name contains an (absolute or relative) path. - - SYNOPSIS - has_path() - name The name to test. - - RETURN - TRUE name contains a path. - FALSE name does not contain a path. -*/ - -my_bool has_path(const char *name) -{ - return test(strchr(name, FN_LIBCHAR)) -#if FN_LIBCHAR != '/' - || test(strchr(name,'/')) -#endif -#ifdef FN_DEVCHAR - || test(strchr(name, FN_DEVCHAR)) -#endif - ; -} diff --git a/dep/mysqllite/mysys/my_handler.c b/dep/mysqllite/mysys/my_handler.c deleted file mode 100644 index bd1e313d066..00000000000 --- a/dep/mysqllite/mysys/my_handler.c +++ /dev/null @@ -1,604 +0,0 @@ -/* Copyright (C) 2002-2006 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 */ - -#include <my_global.h> -#include <m_ctype.h> -#include <my_base.h> -#include <my_handler.h> -#include <my_sys.h> - -#include "my_handler_errors.h" - -#define CMP_NUM(a,b) (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1) - -int ha_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length, - uchar *b, uint b_length, my_bool part_key, - my_bool skip_end_space) -{ - if (!part_key) - return charset_info->coll->strnncollsp(charset_info, a, a_length, - b, b_length, (my_bool)!skip_end_space); - return charset_info->coll->strnncoll(charset_info, a, a_length, - b, b_length, part_key); -} - - -static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length, - my_bool part_key, my_bool skip_end_space) -{ - uint length= min(a_length,b_length); - uchar *end= a+ length; - int flag; - - while (a < end) - if ((flag= (int) *a++ - (int) *b++)) - return flag; - if (part_key && b_length < a_length) - return 0; - if (skip_end_space && a_length != b_length) - { - int swap= 1; - /* - We are using space compression. We have to check if longer key - has next character < ' ', in which case it's less than the shorter - key that has an implicite space afterwards. - - This code is identical to the one in - strings/ctype-simple.c:my_strnncollsp_simple - */ - if (a_length < b_length) - { - /* put shorter key in a */ - a_length= b_length; - a= b; - swap= -1; /* swap sign of result */ - } - for (end= a + a_length-length; a < end ; a++) - { - if (*a != ' ') - return (*a < ' ') ? -swap : swap; - } - return 0; - } - return (int) (a_length-b_length); -} - - -/* - Compare two keys - - SYNOPSIS - ha_key_cmp() - keyseg Array of key segments of key to compare - a First key to compare, in format from _mi_pack_key() - This is normally key specified by user - b Second key to compare. This is always from a row - key_length Length of key to compare. This can be shorter than - a to just compare sub keys - next_flag How keys should be compared - If bit SEARCH_FIND is not set the keys includes the row - position and this should also be compared - diff_pos OUT Number of first keypart where values differ, counting - from one. - diff_pos[1] OUT (b + diff_pos[1]) points to first value in tuple b - that is different from corresponding value in tuple a. - - EXAMPLES - Example1: if the function is called for tuples - ('aaa','bbb') and ('eee','fff'), then - diff_pos[0] = 1 (as 'aaa' != 'eee') - diff_pos[1] = 0 (offset from beggining of tuple b to 'eee' keypart). - - Example2: if the index function is called for tuples - ('aaa','bbb') and ('aaa','fff'), - diff_pos[0] = 2 (as 'aaa' != 'eee') - diff_pos[1] = 3 (offset from beggining of tuple b to 'fff' keypart, - here we assume that first key part is CHAR(3) NOT NULL) - - NOTES - Number-keys can't be splited - - RETURN VALUES - <0 If a < b - 0 If a == b - >0 If a > b -*/ - -#define FCMP(A,B) ((int) (A) - (int) (B)) - -int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a, - register uchar *b, uint key_length, uint nextflag, - uint *diff_pos) -{ - int flag; - int16 s_1,s_2; - int32 l_1,l_2; - uint32 u_1,u_2; - float f_1,f_2; - double d_1,d_2; - uint next_key_length; - uchar *orig_b= b; - - *diff_pos=0; - for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++) - { - uchar *end; - uint piks=! (keyseg->flag & HA_NO_SORT); - (*diff_pos)++; - diff_pos[1]= (uint)(b - orig_b); - - /* Handle NULL part */ - if (keyseg->null_bit) - { - key_length--; - if (*a != *b && piks) - { - flag = (int) *a - (int) *b; - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - } - b++; - if (!*a++) /* If key was NULL */ - { - if (nextflag == (SEARCH_FIND | SEARCH_UPDATE)) - nextflag=SEARCH_SAME; /* Allow duplicate keys */ - else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL) - { - /* - This is only used from mi_check() to calculate cardinality. - It can't be used when searching for a key as this would cause - compare of (a,b) and (b,a) to return the same value. - */ - return -1; - } - next_key_length=key_length; - continue; /* To next key part */ - } - } - end= a+ min(keyseg->length,key_length); - next_key_length=key_length-keyseg->length; - - switch ((enum ha_base_keytype) keyseg->type) { - case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */ - if (keyseg->flag & HA_SPACE_PACK) - { - int a_length,b_length,pack_length; - get_key_length(a_length,a); - get_key_pack_length(b_length,pack_length,b); - next_key_length=key_length-b_length-pack_length; - - if (piks && - (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length, - (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0), - (my_bool)!(nextflag & SEARCH_PREFIX)))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a+=a_length; - b+=b_length; - break; - } - else - { - uint length=(uint) (end-a), a_length=length, b_length=length; - if (piks && - (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length, - (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0), - (my_bool)!(nextflag & SEARCH_PREFIX)))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a=end; - b+=length; - } - break; - case HA_KEYTYPE_BINARY: - case HA_KEYTYPE_BIT: - if (keyseg->flag & HA_SPACE_PACK) - { - int a_length,b_length,pack_length; - get_key_length(a_length,a); - get_key_pack_length(b_length,pack_length,b); - next_key_length=key_length-b_length-pack_length; - - if (piks && - (flag=compare_bin(a,a_length,b,b_length, - (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0),1))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a+=a_length; - b+=b_length; - break; - } - else - { - uint length=keyseg->length; - if (piks && - (flag=compare_bin(a,length,b,length, - (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0),0))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a+=length; - b+=length; - } - break; - case HA_KEYTYPE_VARTEXT1: - case HA_KEYTYPE_VARTEXT2: - { - int a_length,b_length,pack_length; - get_key_length(a_length,a); - get_key_pack_length(b_length,pack_length,b); - next_key_length=key_length-b_length-pack_length; - - if (piks && - (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length, - (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0), - (my_bool) ((nextflag & (SEARCH_FIND | - SEARCH_UPDATE)) == - SEARCH_FIND && - ! (keyseg->flag & - HA_END_SPACE_ARE_EQUAL))))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a+= a_length; - b+= b_length; - break; - } - break; - case HA_KEYTYPE_VARBINARY1: - case HA_KEYTYPE_VARBINARY2: - { - int a_length,b_length,pack_length; - get_key_length(a_length,a); - get_key_pack_length(b_length,pack_length,b); - next_key_length=key_length-b_length-pack_length; - - if (piks && - (flag=compare_bin(a,a_length,b,b_length, - (my_bool) ((nextflag & SEARCH_PREFIX) && - next_key_length <= 0), 0))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a+=a_length; - b+=b_length; - } - break; - case HA_KEYTYPE_INT8: - { - int i_1= (int) *((signed char*) a); - int i_2= (int) *((signed char*) b); - if (piks && (flag = CMP_NUM(i_1,i_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b++; - break; - } - case HA_KEYTYPE_SHORT_INT: - s_1= mi_sint2korr(a); - s_2= mi_sint2korr(b); - if (piks && (flag = CMP_NUM(s_1,s_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 2; /* sizeof(short int); */ - break; - case HA_KEYTYPE_USHORT_INT: - { - uint16 us_1,us_2; - us_1= mi_sint2korr(a); - us_2= mi_sint2korr(b); - if (piks && (flag = CMP_NUM(us_1,us_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+=2; /* sizeof(short int); */ - break; - } - case HA_KEYTYPE_LONG_INT: - l_1= mi_sint4korr(a); - l_2= mi_sint4korr(b); - if (piks && (flag = CMP_NUM(l_1,l_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 4; /* sizeof(long int); */ - break; - case HA_KEYTYPE_ULONG_INT: - u_1= mi_sint4korr(a); - u_2= mi_sint4korr(b); - if (piks && (flag = CMP_NUM(u_1,u_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 4; /* sizeof(long int); */ - break; - case HA_KEYTYPE_INT24: - l_1=mi_sint3korr(a); - l_2=mi_sint3korr(b); - if (piks && (flag = CMP_NUM(l_1,l_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 3; - break; - case HA_KEYTYPE_UINT24: - l_1=mi_uint3korr(a); - l_2=mi_uint3korr(b); - if (piks && (flag = CMP_NUM(l_1,l_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 3; - break; - case HA_KEYTYPE_FLOAT: - mi_float4get(f_1,a); - mi_float4get(f_2,b); - /* - The following may give a compiler warning about floating point - comparison not being safe, but this is ok in this context as - we are bascily doing sorting - */ - if (piks && (flag = CMP_NUM(f_1,f_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 4; /* sizeof(float); */ - break; - case HA_KEYTYPE_DOUBLE: - mi_float8get(d_1,a); - mi_float8get(d_2,b); - /* - The following may give a compiler warning about floating point - comparison not being safe, but this is ok in this context as - we are bascily doing sorting - */ - if (piks && (flag = CMP_NUM(d_1,d_2))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 8; /* sizeof(double); */ - break; - case HA_KEYTYPE_NUM: /* Numeric key */ - { - int swap_flag= 0; - int alength,blength; - - if (keyseg->flag & HA_REVERSE_SORT) - { - swap_variables(uchar*, a, b); - swap_flag=1; /* Remember swap of a & b */ - end= a+ (int) (end-b); - } - if (keyseg->flag & HA_SPACE_PACK) - { - alength= *a++; blength= *b++; - end=a+alength; - next_key_length=key_length-blength-1; - } - else - { - alength= (int) (end-a); - blength=keyseg->length; - /* remove pre space from keys */ - for ( ; alength && *a == ' ' ; a++, alength--) ; - for ( ; blength && *b == ' ' ; b++, blength--) ; - } - if (piks) - { - if (*a == '-') - { - if (*b != '-') - return -1; - a++; b++; - swap_variables(uchar*, a, b); - swap_variables(int, alength, blength); - swap_flag=1-swap_flag; - alength--; blength--; - end=a+alength; - } - else if (*b == '-') - return 1; - while (alength && (*a == '+' || *a == '0')) - { - a++; alength--; - } - while (blength && (*b == '+' || *b == '0')) - { - b++; blength--; - } - if (alength != blength) - return (alength < blength) ? -1 : 1; - while (a < end) - if (*a++ != *b++) - return ((int) a[-1] - (int) b[-1]); - } - else - { - b+=(end-a); - a=end; - } - - if (swap_flag) /* Restore pointers */ - swap_variables(uchar*, a, b); - break; - } -#ifdef HAVE_LONG_LONG - case HA_KEYTYPE_LONGLONG: - { - longlong ll_a,ll_b; - ll_a= mi_sint8korr(a); - ll_b= mi_sint8korr(b); - if (piks && (flag = CMP_NUM(ll_a,ll_b))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 8; - break; - } - case HA_KEYTYPE_ULONGLONG: - { - ulonglong ll_a,ll_b; - ll_a= mi_uint8korr(a); - ll_b= mi_uint8korr(b); - if (piks && (flag = CMP_NUM(ll_a,ll_b))) - return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag); - a= end; - b+= 8; - break; - } -#endif - case HA_KEYTYPE_END: /* Ready */ - goto end; /* diff_pos is incremented */ - } - } - (*diff_pos)++; -end: - if (!(nextflag & SEARCH_FIND)) - { - uint i; - if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */ - return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1; - flag=0; - for (i=keyseg->length ; i-- > 0 ; ) - { - if (*a++ != *b++) - { - flag= FCMP(a[-1],b[-1]); - break; - } - } - if (nextflag & SEARCH_SAME) - return (flag); /* read same */ - if (nextflag & SEARCH_BIGGER) - return (flag <= 0 ? -1 : 1); /* read next */ - return (flag < 0 ? -1 : 1); /* read previous */ - } - return 0; -} /* ha_key_cmp */ - - -/* - Find the first NULL value in index-suffix values tuple - - SYNOPSIS - ha_find_null() - keyseg Array of keyparts for key suffix - a Key suffix value tuple - - DESCRIPTION - Find the first NULL value in index-suffix values tuple. - - TODO - Consider optimizing this function or its use so we don't search for - NULL values in completely NOT NULL index suffixes. - - RETURN - First key part that has NULL as value in values tuple, or the last key - part (with keyseg->type==HA_TYPE_END) if values tuple doesn't contain - NULLs. -*/ - -HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a) -{ - for (; (enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++) - { - uchar *end; - if (keyseg->null_bit) - { - if (!*a++) - return keyseg; - } - end= a+ keyseg->length; - - switch ((enum ha_base_keytype) keyseg->type) { - case HA_KEYTYPE_TEXT: - case HA_KEYTYPE_BINARY: - case HA_KEYTYPE_BIT: - if (keyseg->flag & HA_SPACE_PACK) - { - int a_length; - get_key_length(a_length, a); - a += a_length; - break; - } - else - a= end; - break; - case HA_KEYTYPE_VARTEXT1: - case HA_KEYTYPE_VARTEXT2: - case HA_KEYTYPE_VARBINARY1: - case HA_KEYTYPE_VARBINARY2: - { - int a_length; - get_key_length(a_length, a); - a+= a_length; - break; - } - case HA_KEYTYPE_NUM: - if (keyseg->flag & HA_SPACE_PACK) - { - int alength= *a++; - end= a+alength; - } - a= end; - break; - case HA_KEYTYPE_INT8: - case HA_KEYTYPE_SHORT_INT: - case HA_KEYTYPE_USHORT_INT: - case HA_KEYTYPE_LONG_INT: - case HA_KEYTYPE_ULONG_INT: - case HA_KEYTYPE_INT24: - case HA_KEYTYPE_UINT24: -#ifdef HAVE_LONG_LONG - case HA_KEYTYPE_LONGLONG: - case HA_KEYTYPE_ULONGLONG: -#endif - case HA_KEYTYPE_FLOAT: - case HA_KEYTYPE_DOUBLE: - a= end; - break; - case HA_KEYTYPE_END: /* purecov: inspected */ - /* keep compiler happy */ - DBUG_ASSERT(0); - break; - } - } - return keyseg; -} - - - -/* - Register handler error messages for usage with my_error() - - NOTES - This is safe to call multiple times as my_error_register() - will ignore calls to register already registered error numbers. -*/ - -static const char **get_handler_error_messages() -{ - return handler_error_messages; -} - -void my_handler_error_register(void) -{ - /* - If you got compilation error here about compile_time_assert array, check - that every HA_ERR_xxx constant has a corresponding error message in - handler_error_messages[] list (check mysys/ma_handler_errors.h and - include/my_base.h). - */ - compile_time_assert(HA_ERR_FIRST + array_elements(handler_error_messages) == - HA_ERR_LAST + 1); - my_error_register(get_handler_error_messages, HA_ERR_FIRST, - HA_ERR_FIRST+ array_elements(handler_error_messages)-1); -} - - -void my_handler_error_unregister(void) -{ - my_error_unregister(HA_ERR_FIRST, - HA_ERR_FIRST+ array_elements(handler_error_messages)-1); -} diff --git a/dep/mysqllite/mysys/my_handler_errors.h b/dep/mysqllite/mysys/my_handler_errors.h deleted file mode 100644 index e4e62f47fed..00000000000 --- a/dep/mysqllite/mysys/my_handler_errors.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef MYSYS_MY_HANDLER_ERRORS_INCLUDED -#define MYSYS_MY_HANDLER_ERRORS_INCLUDED - -/* - Errors a handler can give you -*/ - -static const char *handler_error_messages[]= -{ - "Didn't find key on read or update", - "Duplicate key on write or update", - "Internal (unspecified) error in handler", - "Someone has changed the row since it was read (while the table was locked to prevent it)", - "Wrong index given to function", - "Undefined handler error 125", - "Index file is crashed", - "Record file is crashed", - "Out of memory in engine", - "Undefined handler error 129", - "Incorrect file format", - "Command not supported by database", - "Old database file", - "No record read before update", - "Record was already deleted (or record file crashed)", - "No more room in record file", - "No more room in index file", - "No more records (read after end of file)", - "Unsupported extension used for table", - "Too big row", - "Wrong create options", - "Duplicate unique key or constraint on write or update", - "Unknown character set used in table", - "Conflicting table definitions in sub-tables of MERGE table", - "Table is crashed and last repair failed", - "Table was marked as crashed and should be repaired", - "Lock timed out; Retry transaction", - "Lock table is full; Restart program with a larger locktable", - "Updates are not allowed under a read only transactions", - "Lock deadlock; Retry transaction", - "Foreign key constraint is incorrectly formed", - "Cannot add a child row", - "Cannot delete a parent row", - "No savepoint with that name", - "Non unique key block size", - "The table does not exist in engine", - "The table already existed in storage engine", - "Could not connect to storage engine", - "Unexpected null pointer found when using spatial index", - "The table changed in storage engine", - "There's no partition in table for the given value", - "Row-based binlogging of row failed", - "Index needed in foreign key constraint", - "Upholding foreign key constraints would lead to a duplicate key error in " - "some other table", - "Table needs to be upgraded before it can be used", - "Table is read only", - "Failed to get next auto increment value", - "Failed to set row auto increment value", - "Unknown (generic) error from engine", - "Record is the same", - "It is not possible to log this statement", - "The event was corrupt, leading to illegal data being read", - "The table is of a new format not supported by this version", - "The event could not be processed no other hanlder error happened", - "Got a fatal error during initialzaction of handler", - "File to short; Expected more data in file", - "Read page with wrong checksum", - "Too many active concurrent transactions" -}; - -#endif /* MYSYS_MY_HANDLER_ERRORS_INCLUDED */ diff --git a/dep/mysqllite/mysys/my_init.c b/dep/mysqllite/mysys/my_init.c deleted file mode 100644 index 9b0939c1c75..00000000000 --- a/dep/mysqllite/mysys/my_init.c +++ /dev/null @@ -1,607 +0,0 @@ -/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 "my_static.h" -#include "mysys_err.h" -#include <m_string.h> -#include <m_ctype.h> -#include <signal.h> -#ifdef __WIN__ -#ifdef _MSC_VER -#include <locale.h> -#include <crtdbg.h> -/* WSAStartup needs winsock library*/ -#pragma comment(lib, "ws2_32") -#endif -my_bool have_tcpip=0; -static void my_win_init(void); -static my_bool win32_init_tcp_ip(); -#else -#define my_win_init() -#endif - -#define SCALE_SEC 100 -#define SCALE_USEC 10000 - -my_bool my_init_done= 0; -/** True if @c my_basic_init() has been called. */ -my_bool my_basic_init_done= 0; -uint mysys_usage_id= 0; /* Incremented for each my_init() */ -ulong my_thread_stack_size= 65536; - -static ulong atoi_octal(const char *str) -{ - long int tmp; - while (*str && my_isspace(&my_charset_latin1, *str)) - str++; - str2int(str, - (*str == '0' ? 8 : 10), /* Octalt or decimalt */ - 0, INT_MAX, &tmp); - return (ulong) tmp; -} - -MYSQL_FILE *mysql_stdin= NULL; -static MYSQL_FILE instrumented_stdin; - -/** - Perform a limited initialisation of mysys. - This initialisation is sufficient to: - - allocate memory, - - read configuration files, - - parse command lines arguments. - To complete the mysys initialisation, - call my_init(). - @return 0 on success -*/ -my_bool my_basic_init(void) -{ - char * str; - - if (my_basic_init_done) - return 0; - my_basic_init_done= 1; - - mysys_usage_id++; - my_umask= 0660; /* Default umask for new files */ - my_umask_dir= 0700; /* Default umask for new directories */ - - /* Default creation of new files */ - if ((str= getenv("UMASK")) != 0) - my_umask= (int) (atoi_octal(str) | 0600); - /* Default creation of new dir's */ - if ((str= getenv("UMASK_DIR")) != 0) - my_umask_dir= (int) (atoi_octal(str) | 0700); - - init_glob_errs(); - - instrumented_stdin.m_file= stdin; - instrumented_stdin.m_psi= NULL; /* not yet instrumented */ - mysql_stdin= & instrumented_stdin; - - if (my_thread_global_init()) - return 1; - -#if defined(SAFE_MUTEX) - safe_mutex_global_init(); /* Must be called early */ -#endif - -#if defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) - fastmutex_global_init(); /* Must be called early */ -#endif - -#if defined(HAVE_PTHREAD_INIT) - pthread_init(); /* Must be called before DBUG_ENTER */ -#endif - if (my_thread_basic_global_init()) - return 1; - - /* $HOME is needed early to parse configuration files located in ~/ */ - if ((home_dir= getenv("HOME")) != 0) - home_dir= intern_filename(home_dir_buff, home_dir); - - return 0; -} - - -/* - Init my_sys functions and my_sys variabels - - SYNOPSIS - my_init() - - RETURN - 0 ok - 1 Couldn't initialize environment -*/ - -my_bool my_init(void) -{ - if (my_init_done) - return 0; - - my_init_done= 1; - - if (my_basic_init()) - return 1; - - if (my_thread_global_init()) - return 1; - - { - DBUG_ENTER("my_init"); - DBUG_PROCESS((char*) (my_progname ? my_progname : "unknown")); - my_win_init(); - DBUG_PRINT("exit", ("home: '%s'", home_dir)); -#ifdef __WIN__ - win32_init_tcp_ip(); -#endif - DBUG_RETURN(0); - } -} /* my_init */ - - - /* End my_sys */ - -void my_end(int infoflag) -{ - /* - this code is suboptimal to workaround a bug in - Sun CC: Sun C++ 5.6 2004/06/02 for x86, and should not be - optimized until this compiler is not in use anymore - */ - FILE *info_file= DBUG_FILE; - my_bool print_info= (info_file != stderr); - - if (!my_init_done) - return; - - /* - 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: infoflag: %d print_info: %d", - infoflag, print_info)); - if (!info_file) - { - info_file= stderr; - print_info= 0; - } - - if ((infoflag & MY_CHECK_ERROR) || print_info) - - { /* Test if some file is left open */ - if (my_file_opened | my_stream_opened) - { - char ebuff[512]; - my_snprintf(ebuff, sizeof(ebuff), EE(EE_OPEN_WARNING), - my_file_opened, my_stream_opened); - my_message_stderr(EE_OPEN_WARNING, ebuff, ME_BELL); - DBUG_PRINT("error", ("%s", ebuff)); - my_print_open_files(); - } - } - free_charsets(); - my_error_unregister_all(); - my_once_free(); - - if ((infoflag & MY_GIVE_INFO) || print_info) - { -#ifdef HAVE_GETRUSAGE - struct rusage rus; -#ifdef HAVE_purify - /* Purify assumes that rus is uninitialized after getrusage call */ - bzero((char*) &rus, sizeof(rus)); -#endif - if (!getrusage(RUSAGE_SELF, &rus)) - fprintf(info_file,"\n\ -User time %.2f, System time %.2f\n\ -Maximum resident set size %ld, Integral resident set size %ld\n\ -Non-physical pagefaults %ld, Physical pagefaults %ld, Swaps %ld\n\ -Blocks in %ld out %ld, Messages in %ld out %ld, Signals %ld\n\ -Voluntary context switches %ld, Involuntary context switches %ld\n", - (rus.ru_utime.tv_sec * SCALE_SEC + - rus.ru_utime.tv_usec / SCALE_USEC) / 100.0, - (rus.ru_stime.tv_sec * SCALE_SEC + - rus.ru_stime.tv_usec / SCALE_USEC) / 100.0, - rus.ru_maxrss, rus.ru_idrss, - rus.ru_minflt, rus.ru_majflt, - rus.ru_nswap, rus.ru_inblock, rus.ru_oublock, - rus.ru_msgsnd, rus.ru_msgrcv, rus.ru_nsignals, - rus.ru_nvcsw, rus.ru_nivcsw); -#endif -#if defined(__WIN__) && defined(_MSC_VER) - _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR ); - _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR ); - _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); - _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR ); - _CrtCheckMemory(); - _CrtDumpMemoryLeaks(); -#endif - } - - if (!(infoflag & MY_DONT_FREE_DBUG)) - { - DBUG_END(); /* Must be done before my_thread_end */ - } - - my_thread_end(); - my_thread_global_end(); -#if defined(SAFE_MUTEX) - /* - 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 | MY_CHECK_ERROR)) ? stderr : - (FILE *) 0); -#endif /* defined(SAFE_MUTEX) */ - -#ifdef __WIN__ - if (have_tcpip) - WSACleanup(); -#endif /* __WIN__ */ - - my_init_done=0; - my_basic_init_done= 0; -} /* my_end */ - - -#ifdef __WIN__ - - -/* - my_parameter_handler - - Invalid parameter handler we will use instead of the one "baked" - into the CRT for MSC v8. This one just prints out what invalid - parameter was encountered. By providing this routine, routines like - lseek will return -1 when we expect them to instead of crash. -*/ - -void my_parameter_handler(const wchar_t * expression, const wchar_t * function, - const wchar_t * file, unsigned int line, - uintptr_t pReserved) -{ - DBUG_PRINT("my",("Expression: %s function: %s file: %s, line: %d", - expression, function, file, line)); -} - - -#ifdef __MSVC_RUNTIME_CHECKS -#include <rtcapi.h> - -/* Turn off runtime checks for 'handle_rtc_failure' */ -#pragma runtime_checks("", off) - -/* - handle_rtc_failure - Catch the RTC error and dump it to stderr -*/ - -int handle_rtc_failure(int err_type, const char *file, int line, - const char* module, const char *format, ...) -{ - va_list args; - va_start(args, format); - fprintf(stderr, "Error:"); - vfprintf(stderr, format, args); - fprintf(stderr, " At %s:%d\n", file, line); - va_end(args); - (void) fflush(stderr); - - return 0; /* Error is handled */ -} -#pragma runtime_checks("", restore) -#endif - -#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10) -#define MS 10000000 - -static void win_init_time(void) -{ - /* The following is used by time functions */ - FILETIME ft; - LARGE_INTEGER li, t_cnt; - - DBUG_ASSERT(sizeof(LARGE_INTEGER) == sizeof(query_performance_frequency)); - - if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency) == 0) - query_performance_frequency= 0; - else - { - GetSystemTimeAsFileTime(&ft); - li.LowPart= ft.dwLowDateTime; - li.HighPart= ft.dwHighDateTime; - query_performance_offset= li.QuadPart-OFFSET_TO_EPOC; - QueryPerformanceCounter(&t_cnt); - query_performance_offset-= (t_cnt.QuadPart / - query_performance_frequency * MS + - t_cnt.QuadPart % - query_performance_frequency * MS / - query_performance_frequency); - } -} - - -/* - Open HKEY_LOCAL_MACHINE\SOFTWARE\MySQL and set any strings found - there as environment variables -*/ -static void win_init_registry(void) -{ - HKEY key_handle; - - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, (LPCTSTR)"SOFTWARE\\MySQL", - 0, KEY_READ, &key_handle) == ERROR_SUCCESS) - { - LONG ret; - DWORD index= 0; - DWORD type; - char key_name[256], key_data[1024]; - DWORD key_name_len= sizeof(key_name) - 1; - DWORD key_data_len= sizeof(key_data) - 1; - - while ((ret= RegEnumValue(key_handle, index++, - key_name, &key_name_len, - NULL, &type, (LPBYTE)&key_data, - &key_data_len)) != ERROR_NO_MORE_ITEMS) - { - char env_string[sizeof(key_name) + sizeof(key_data) + 2]; - - if (ret == ERROR_MORE_DATA) - { - /* Registry value larger than 'key_data', skip it */ - DBUG_PRINT("error", ("Skipped registry value that was too large")); - } - else if (ret == ERROR_SUCCESS) - { - if (type == REG_SZ) - { - strxmov(env_string, key_name, "=", key_data, NullS); - - /* variable for putenv must be allocated ! */ - putenv(strdup(env_string)) ; - } - } - else - { - /* Unhandled error, break out of loop */ - break; - } - - key_name_len= sizeof(key_name) - 1; - key_data_len= sizeof(key_data) - 1; - } - - RegCloseKey(key_handle); - } -} - - -static void my_win_init(void) -{ - DBUG_ENTER("my_win_init"); - -#if defined(_MSC_VER) -#if _MSC_VER < 1300 - /* - Clear the OS system variable TZ and avoid the 100% CPU usage - Only for old versions of Visual C++ - */ - _putenv("TZ="); -#endif -#if _MSC_VER >= 1400 - /* this is required to make crt functions return -1 appropriately */ - _set_invalid_parameter_handler(my_parameter_handler); -#endif -#endif - -#ifdef __MSVC_RUNTIME_CHECKS - /* - Install handler to send RTC (Runtime Error Check) warnings - to log file - */ - _RTC_SetErrorFunc(handle_rtc_failure); -#endif - - _tzset(); - - win_init_time(); - win_init_registry(); - - DBUG_VOID_RETURN; -} - - -/*------------------------------------------------------------------ - Name: CheckForTcpip| Desc: checks if tcpip has been installed on system - According to Microsoft Developers documentation the first registry - entry should be enough to check if TCP/IP is installed, but as expected - this doesn't work on all Win32 machines :( -------------------------------------------------------------------*/ - -#define TCPIPKEY "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters" -#define WINSOCK2KEY "SYSTEM\\CurrentControlSet\\Services\\Winsock2\\Parameters" -#define WINSOCKKEY "SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters" - -static my_bool win32_have_tcpip(void) -{ - HKEY hTcpipRegKey; - if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, TCPIPKEY, 0, KEY_READ, - &hTcpipRegKey) != ERROR_SUCCESS) - { - if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, WINSOCK2KEY, 0, KEY_READ, - &hTcpipRegKey) != ERROR_SUCCESS) - { - if (RegOpenKeyEx ( HKEY_LOCAL_MACHINE, WINSOCKKEY, 0, KEY_READ, - &hTcpipRegKey) != ERROR_SUCCESS) - if (!getenv("HAVE_TCPIP") || have_tcpip) /* Provide a workaround */ - return (FALSE); - } - } - RegCloseKey ( hTcpipRegKey); - return (TRUE); -} - - -static my_bool win32_init_tcp_ip() -{ - if (win32_have_tcpip()) - { - WORD wVersionRequested = MAKEWORD( 2, 2 ); - WSADATA wsaData; - /* Be a good citizen: maybe another lib has already initialised - sockets, so dont clobber them unless necessary */ - if (WSAStartup( wVersionRequested, &wsaData )) - { - /* Load failed, maybe because of previously loaded - incompatible version; try again */ - WSACleanup( ); - if (!WSAStartup( wVersionRequested, &wsaData )) - have_tcpip=1; - } - else - { - if (wsaData.wVersion != wVersionRequested) - { - /* Version is no good, try again */ - WSACleanup( ); - if (!WSAStartup( wVersionRequested, &wsaData )) - have_tcpip=1; - } - else - have_tcpip=1; - } - } - return(0); -} -#endif /* __WIN__ */ - -#ifdef HAVE_PSI_INTERFACE - -#if !defined(HAVE_PREAD) && !defined(_WIN32) -PSI_mutex_key key_my_file_info_mutex; -#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */ - -#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) -PSI_mutex_key key_LOCK_localtime_r; -#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ - -#ifndef HAVE_GETHOSTBYNAME_R -PSI_mutex_key key_LOCK_gethostbyname_r; -#endif /* HAVE_GETHOSTBYNAME_R */ - -PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, - key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm, - key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, - key_THR_LOCK_isam, key_THR_LOCK_lock, key_THR_LOCK_malloc, - key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, - key_THR_LOCK_open, key_THR_LOCK_threads, key_THR_LOCK_time, - key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap; - -static PSI_mutex_info all_mysys_mutexes[]= -{ -#if !defined(HAVE_PREAD) && !defined(_WIN32) - { &key_my_file_info_mutex, "st_my_file_info:mutex", 0}, -#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */ -#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) - { &key_LOCK_localtime_r, "LOCK_localtime_r", PSI_FLAG_GLOBAL}, -#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ -#ifndef HAVE_GETHOSTBYNAME_R - { &key_LOCK_gethostbyname_r, "LOCK_gethostbyname_r", PSI_FLAG_GLOBAL}, -#endif /* HAVE_GETHOSTBYNAME_R */ - { &key_BITMAP_mutex, "BITMAP::mutex", 0}, - { &key_IO_CACHE_append_buffer_lock, "IO_CACHE::append_buffer_lock", 0}, - { &key_IO_CACHE_SHARE_mutex, "IO_CACHE::SHARE_mutex", 0}, - { &key_KEY_CACHE_cache_lock, "KEY_CACHE::cache_lock", 0}, - { &key_LOCK_alarm, "LOCK_alarm", PSI_FLAG_GLOBAL}, - { &key_my_thread_var_mutex, "my_thread_var::mutex", 0}, - { &key_THR_LOCK_charset, "THR_LOCK_charset", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_heap, "THR_LOCK_heap", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_isam, "THR_LOCK_isam", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_lock, "THR_LOCK_lock", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_malloc, "THR_LOCK_malloc", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_mutex, "THR_LOCK::mutex", 0}, - { &key_THR_LOCK_myisam, "THR_LOCK_myisam", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_net, "THR_LOCK_net", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_open, "THR_LOCK_open", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_threads, "THR_LOCK_threads", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_time, "THR_LOCK_time", PSI_FLAG_GLOBAL}, - { &key_TMPDIR_mutex, "TMPDIR_mutex", PSI_FLAG_GLOBAL}, - { &key_THR_LOCK_myisam_mmap, "THR_LOCK_myisam_mmap", PSI_FLAG_GLOBAL} -}; - -PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond, - key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend, - key_THR_COND_threads; - -static PSI_cond_info all_mysys_conds[]= -{ - { &key_COND_alarm, "COND_alarm", PSI_FLAG_GLOBAL}, - { &key_IO_CACHE_SHARE_cond, "IO_CACHE_SHARE::cond", 0}, - { &key_IO_CACHE_SHARE_cond_writer, "IO_CACHE_SHARE::cond_writer", 0}, - { &key_my_thread_var_suspend, "my_thread_var::suspend", 0}, - { &key_THR_COND_threads, "THR_COND_threads", 0} -}; - -#ifdef USE_ALARM_THREAD -PSI_thread_key key_thread_alarm; - -static PSI_thread_info all_mysys_threads[]= -{ - { &key_thread_alarm, "alarm", PSI_FLAG_GLOBAL} -}; -#endif /* USE_ALARM_THREAD */ - -#ifdef HUGETLB_USE_PROC_MEMINFO -PSI_file_key key_file_proc_meminfo; -#endif /* HUGETLB_USE_PROC_MEMINFO */ -PSI_file_key key_file_charset, key_file_cnf; - -static PSI_file_info all_mysys_files[]= -{ -#ifdef HUGETLB_USE_PROC_MEMINFO - { &key_file_proc_meminfo, "proc_meminfo", 0}, -#endif /* HUGETLB_USE_PROC_MEMINFO */ - { &key_file_charset, "charset", 0}, - { &key_file_cnf, "cnf", 0} -}; - -void my_init_mysys_psi_keys() -{ - const char* category= "mysys"; - int count; - - if (PSI_server == NULL) - return; - - count= sizeof(all_mysys_mutexes)/sizeof(all_mysys_mutexes[0]); - PSI_server->register_mutex(category, all_mysys_mutexes, count); - - count= sizeof(all_mysys_conds)/sizeof(all_mysys_conds[0]); - PSI_server->register_cond(category, all_mysys_conds, count); - -#ifdef USE_ALARM_THREAD - count= sizeof(all_mysys_threads)/sizeof(all_mysys_threads[0]); - PSI_server->register_thread(category, all_mysys_threads, count); -#endif /* USE_ALARM_THREAD */ - - count= sizeof(all_mysys_files)/sizeof(all_mysys_files[0]); - PSI_server->register_file(category, all_mysys_files, count); -} -#endif /* HAVE_PSI_INTERFACE */ - diff --git a/dep/mysqllite/mysys/my_largepage.c b/dep/mysqllite/mysys/my_largepage.c deleted file mode 100644 index 9f5ab01a2b7..00000000000 --- a/dep/mysqllite/mysys/my_largepage.c +++ /dev/null @@ -1,166 +0,0 @@ -/* Copyright (C) 2004 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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" - -#ifdef HAVE_LARGE_PAGES - -#ifdef HAVE_SYS_IPC_H -#include <sys/ipc.h> -#endif - -#ifdef HAVE_SYS_SHM_H -#include <sys/shm.h> -#endif - -static uint my_get_large_page_size_int(void); -static uchar* my_large_malloc_int(size_t size, myf my_flags); -static my_bool my_large_free_int(uchar* ptr); - -/* Gets the size of large pages from the OS */ - -uint my_get_large_page_size(void) -{ - uint size; - DBUG_ENTER("my_get_large_page_size"); - - if (!(size = my_get_large_page_size_int())) - fprintf(stderr, "Warning: Failed to determine large page size\n"); - - DBUG_RETURN(size); -} - -/* - General large pages allocator. - Tries to allocate memory from large pages pool and falls back to - my_malloc_lock() in case of failure -*/ - -uchar* my_large_malloc(size_t size, myf my_flags) -{ - uchar* ptr; - DBUG_ENTER("my_large_malloc"); - - if (my_use_large_pages && my_large_page_size) - { - if ((ptr = my_large_malloc_int(size, my_flags)) != NULL) - DBUG_RETURN(ptr); - if (my_flags & MY_WME) - fprintf(stderr, "Warning: Using conventional memory pool\n"); - } - - DBUG_RETURN(my_malloc_lock(size, my_flags)); -} - -/* - General large pages deallocator. - Tries to deallocate memory as if it was from large pages pool and falls back - to my_free_lock() in case of failure - */ - -void my_large_free(uchar* ptr) -{ - DBUG_ENTER("my_large_free"); - - /* - my_large_free_int() can only fail if ptr was not allocated with - my_large_malloc_int(), i.e. my_malloc_lock() was used so we should free it - with my_free_lock() - */ - if (!my_use_large_pages || !my_large_page_size || !my_large_free_int(ptr)) - my_free_lock(ptr); - - DBUG_VOID_RETURN; -} - -#ifdef HUGETLB_USE_PROC_MEMINFO -/* Linux-specific function to determine the size of large pages */ - -uint my_get_large_page_size_int(void) -{ - MYSQL_FILE *f; - uint size = 0; - char buf[256]; - DBUG_ENTER("my_get_large_page_size_int"); - - if (!(f= mysql_file_fopen(key_file_proc_meminfo, "/proc/meminfo", - O_RDONLY, MYF(MY_WME)))) - goto finish; - - while (mysql_file_fgets(buf, sizeof(buf), f)) - if (sscanf(buf, "Hugepagesize: %u kB", &size)) - break; - - mysql_file_fclose(f, MYF(MY_WME)); - -finish: - DBUG_RETURN(size * 1024); -} -#endif /* HUGETLB_USE_PROC_MEMINFO */ - -#if HAVE_DECL_SHM_HUGETLB -/* Linux-specific large pages allocator */ - -uchar* my_large_malloc_int(size_t size, myf my_flags) -{ - int shmid; - uchar* ptr; - struct shmid_ds buf; - DBUG_ENTER("my_large_malloc_int"); - - /* Align block size to my_large_page_size */ - size= MY_ALIGN(size, (size_t) my_large_page_size); - - shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | SHM_R | SHM_W); - if (shmid < 0) - { - if (my_flags & MY_WME) - fprintf(stderr, - "Warning: Failed to allocate %lu bytes from HugeTLB memory." - " errno %d\n", (ulong) size, errno); - - DBUG_RETURN(NULL); - } - - ptr = (uchar*) shmat(shmid, NULL, 0); - if (ptr == (uchar *) -1) - { - if (my_flags& MY_WME) - fprintf(stderr, "Warning: Failed to attach shared memory segment," - " errno %d\n", errno); - shmctl(shmid, IPC_RMID, &buf); - - DBUG_RETURN(NULL); - } - - /* - Remove the shared memory segment so that it will be automatically freed - after memory is detached or process exits - */ - shmctl(shmid, IPC_RMID, &buf); - - DBUG_RETURN(ptr); -} - -/* Linux-specific large pages deallocator */ - -my_bool my_large_free_int(uchar *ptr) -{ - DBUG_ENTER("my_large_free_int"); - DBUG_RETURN(shmdt(ptr) == 0); -} -#endif /* HAVE_DECL_SHM_HUGETLB */ - -#endif /* HAVE_LARGE_PAGES */ diff --git a/dep/mysqllite/mysys/my_lib.c b/dep/mysqllite/mysys/my_lib.c deleted file mode 100644 index 06f9521a664..00000000000 --- a/dep/mysqllite/mysys/my_lib.c +++ /dev/null @@ -1,424 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* TODO: check for overun of memory for names. */ - -#include "mysys_priv.h" -#include <m_string.h> -#include <my_dir.h> /* Structs used by my_dir,includes sys/types */ -#include "mysys_err.h" -#if defined(HAVE_DIRENT_H) -# include <dirent.h> -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# if defined(HAVE_SYS_NDIR_H) -# include <sys/ndir.h> -# endif -# if defined(HAVE_SYS_DIR_H) -# include <sys/dir.h> -# endif -# if defined(HAVE_NDIR_H) -# include <ndir.h> -# endif -# if defined(_WIN32) -# ifdef __BORLANDC__ -# include <dir.h> -# endif -# endif -#endif - -#if defined(HAVE_READDIR_R) -#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C) -#else -#define READDIR(A,B,C) (!(C=readdir(A))) -#endif - -/* - We are assuming that directory we are reading is either has less than - 100 files and so can be read in one initial chunk or has more than 1000 - files and so big increment are suitable. -*/ -#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO)) -#define ENTRIES_INCREMENT (65536/sizeof(FILEINFO)) -#define NAMES_START_SIZE 32768 - - -static int comp_names(struct fileinfo *a,struct fileinfo *b); - - - /* We need this because program don't know with malloc we used */ - -void my_dirend(MY_DIR *buffer) -{ - DBUG_ENTER("my_dirend"); - if (buffer) - { - delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer + - ALIGN_SIZE(sizeof(MY_DIR)))); - free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) + - ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0)); - my_free(buffer); - } - DBUG_VOID_RETURN; -} /* my_dirend */ - - - /* Compare in sort of filenames */ - -static int comp_names(struct fileinfo *a, struct fileinfo *b) -{ - return (strcmp(a->name,b->name)); -} /* comp_names */ - - -#if !defined(_WIN32) - -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; - DIR *dirp; - struct dirent *dp; - char tmp_path[FN_REFLEN+1],*tmp_file; - char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1]; - - DBUG_ENTER("my_dir"); - DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags)); - -#if !defined(HAVE_READDIR_R) - mysql_mutex_lock(&THR_LOCK_open); -#endif - - dirp = opendir(directory_file_name(tmp_path,(char *) path)); -#if defined(__amiga__) - if ((dirp->dd_fd) < 0) /* Directory doesn't exists */ - goto error; -#endif - if (dirp == NULL || - ! (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(buffer); - 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; - - tmp_file=strend(tmp_path); - - dp= (struct dirent*) dirent_tmp; - - while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp))) - { - if (!(finfo.name= strdup_root(names_storage, dp->d_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)); - (void) strmov(tmp_file,dp->d_name); - (void) my_stat(tmp_path, finfo.mystat, MyFlags); - if (!(finfo.mystat->st_mode & MY_S_IREAD)) - continue; - } - else - finfo.mystat= NULL; - - if (push_dynamic(dir_entries_storage, (uchar*)&finfo)) - goto error; - } - - (void) closedir(dirp); -#if !defined(HAVE_READDIR_R) - mysql_mutex_unlock(&THR_LOCK_open); -#endif - result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; - result->number_off_files= dir_entries_storage->elements; - - if (!(MyFlags & MY_DONT_SORT)) - my_qsort((void *) result->dir_entry, result->number_off_files, - sizeof(FILEINFO), (qsort_cmp) comp_names); - DBUG_RETURN(result); - - error: -#if !defined(HAVE_READDIR_R) - mysql_mutex_unlock(&THR_LOCK_open); -#endif - my_errno=errno; - if (dirp) - (void) closedir(dirp); - my_dirend(result); - if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno); - DBUG_RETURN((MY_DIR *) NULL); -} /* my_dir */ - - -/* - * Convert from directory name to filename. - * On UNIX, it's simple: just make sure there is a terminating / - - * Returns pointer to dst; - */ - -char * directory_file_name (char * dst, const char *src) -{ - /* Process as Unix format: just remove test the final slash. */ - char *end; - - if (src[0] == 0) - src= (char*) "."; /* Use empty as current */ - end=strmov(dst, src); - if (end[-1] != FN_LIBCHAR) - { - end[0]=FN_LIBCHAR; /* Add last '/' */ - end[1]='\0'; - } - return dst; -} - -#else - -/* -***************************************************************************** -** Read long filename using windows rutines -***************************************************************************** -*/ - -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; -#ifdef __BORLANDC__ - struct ffblk find; -#else - struct _finddata_t find; -#endif - ushort mode; - char tmp_path[FN_REFLEN],*tmp_file,attrib; -#ifdef _WIN64 - __int64 handle; -#else - long handle; -#endif - 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= strnmov(tmp_file, path, FN_REFLEN-5); - 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]='*'; /* Windows needs this !??? */ - tmp_file[1]='.'; - tmp_file[2]='*'; - tmp_file[3]='\0'; - - 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(buffer); - 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; - -#ifdef __BORLANDC__ - if ((handle= findfirst(tmp_path,&find,0)) == -1L) -#else - if ((handle=_findfirst(tmp_path,&find)) == -1L) -#endif - { - DBUG_PRINT("info", ("findfirst returned error, errno: %d", errno)); - if (errno != EINVAL) - goto error; - /* - Could not read the directory, no read access. - Probably because by "chmod -r". - continue and return zero files in dir - */ - } - else - { - - do - { -#ifdef __BORLANDC__ - attrib= find.ff_attrib; -#else - attrib= find.attrib; - /* - Do not show hidden and system files which Windows sometimes create. - Note. Because Borland's findfirst() is called with the third - argument = 0 hidden/system files are excluded from the search. - */ - if (attrib & (_A_HIDDEN | _A_SYSTEM)) - continue; -#endif -#ifdef __BORLANDC__ - if (!(finfo.name= strdup_root(names_storage, find.ff_name))) - goto error; -#else - if (!(finfo.name= strdup_root(names_storage, find.name))) - goto error; -#endif - 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)); -#ifdef __BORLANDC__ - finfo.mystat->st_size=find.ff_fsize; -#else - finfo.mystat->st_size=find.size; -#endif - mode= MY_S_IREAD; - if (!(attrib & _A_RDONLY)) - mode|= MY_S_IWRITE; - if (attrib & _A_SUBDIR) - mode|= MY_S_IFDIR; - finfo.mystat->st_mode= mode; -#ifdef __BORLANDC__ - finfo.mystat->st_mtime= ((uint32) find.ff_ftime); -#else - finfo.mystat->st_mtime= ((uint32) find.time_write); -#endif - } - else - finfo.mystat= NULL; - - if (push_dynamic(dir_entries_storage, (uchar*)&finfo)) - goto error; - } -#ifdef __BORLANDC__ - while (findnext(&find) == 0); -#else - while (_findnext(handle,&find) == 0); - - _findclose(handle); -#endif - } - - result->dir_entry= (FILEINFO *)dir_entries_storage->buffer; - result->number_off_files= dir_entries_storage->elements; - - if (!(MyFlags & MY_DONT_SORT)) - my_qsort((void *) result->dir_entry, result->number_off_files, - sizeof(FILEINFO), (qsort_cmp) comp_names); - DBUG_PRINT("exit", ("found %d files", result->number_off_files)); - DBUG_RETURN(result); -error: - my_errno=errno; -#ifndef __BORLANDC__ - if (handle != -1) - _findclose(handle); -#endif - 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 */ - -/**************************************************************************** -** File status -** Note that MY_STAT is assumed to be same as struct stat -****************************************************************************/ - - -int my_fstat(File Filedes, MY_STAT *stat_area, - myf MyFlags __attribute__((unused))) -{ - DBUG_ENTER("my_fstat"); - DBUG_PRINT("my",("fd: %d MyFlags: %d", Filedes, MyFlags)); -#ifdef _WIN32 - DBUG_RETURN(my_win_fstat(Filedes, stat_area)); -#else - DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area)); -#endif -} - - -MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags) -{ - int m_used; - DBUG_ENTER("my_stat"); - DBUG_PRINT("my", ("path: '%s' stat_area: 0x%lx MyFlags: %d", path, - (long) stat_area, my_flags)); - - if ((m_used= (stat_area == NULL))) - if (!(stat_area= (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags))) - goto error; -#ifndef _WIN32 - if (! stat((char *) path, (struct stat *) stat_area) ) - DBUG_RETURN(stat_area); -#else - if (! my_win_stat(path, stat_area) ) - DBUG_RETURN(stat_area); -#endif - DBUG_PRINT("error",("Got errno: %d from stat", errno)); - my_errno= errno; - if (m_used) /* Free if new area */ - my_free(stat_area); - -error: - if (my_flags & (MY_FAE+MY_WME)) - { - my_error(EE_STAT, MYF(ME_BELL+ME_WAITTANG),path,my_errno); - DBUG_RETURN((MY_STAT *) NULL); - } - DBUG_RETURN((MY_STAT *) NULL); -} /* my_stat */ diff --git a/dep/mysqllite/mysys/my_libwrap.c b/dep/mysqllite/mysys/my_libwrap.c deleted file mode 100644 index e72334ba806..00000000000 --- a/dep/mysqllite/mysys/my_libwrap.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2003 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 */ - -/* - This is needed to be able to compile with original libwrap header - files that don't have the prototypes -*/ - -#include <my_global.h> -#include <my_libwrap.h> - -#ifdef HAVE_LIBWRAP - -void my_fromhost(struct request_info *req) -{ - fromhost(req); -} - -int my_hosts_access(struct request_info *req) -{ - return hosts_access(req); -} - -char *my_eval_client(struct request_info *req) -{ - return eval_client(req); -} - -#endif /* HAVE_LIBWRAP */ diff --git a/dep/mysqllite/mysys/my_lock.c b/dep/mysqllite/mysys/my_lock.c deleted file mode 100644 index 49c94ea838c..00000000000 --- a/dep/mysqllite/mysys/my_lock.c +++ /dev/null @@ -1,223 +0,0 @@ -/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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" -#include <errno.h> -#undef MY_HOW_OFTEN_TO_ALARM -#define MY_HOW_OFTEN_TO_ALARM ((int) my_time_to_wait_for_lock) -#ifdef NO_ALARM_LOOP -#undef NO_ALARM_LOOP -#endif -#include <my_alarm.h> - -#ifdef _WIN32 -#define WIN_LOCK_INFINITE -1 -#define WIN_LOCK_SLEEP_MILLIS 100 - -static int win_lock(File fd, int locktype, my_off_t start, my_off_t length, - int timeout_sec) -{ - LARGE_INTEGER liOffset,liLength; - DWORD dwFlags; - OVERLAPPED ov= {0}; - HANDLE hFile= (HANDLE)my_get_osfhandle(fd); - DWORD lastError= 0; - int i; - int timeout_millis= timeout_sec * 1000; - - DBUG_ENTER("win_lock"); - - liOffset.QuadPart= start; - liLength.QuadPart= length; - - ov.Offset= liOffset.LowPart; - ov.OffsetHigh= liOffset.HighPart; - - if (locktype == F_UNLCK) - { - if (UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov)) - DBUG_RETURN(0); - /* - For compatibility with fcntl implementation, ignore error, - if region was not locked - */ - if (GetLastError() == ERROR_NOT_LOCKED) - { - SetLastError(0); - DBUG_RETURN(0); - } - goto error; - } - else if (locktype == F_RDLCK) - /* read lock is mapped to a shared lock. */ - dwFlags= 0; - else - /* write lock is mapped to an exclusive lock. */ - dwFlags= LOCKFILE_EXCLUSIVE_LOCK; - - /* - Drop old lock first to avoid double locking. - During analyze of Bug#38133 (Myisamlog test fails on Windows) - I met the situation that the program myisamlog locked the file - exclusively, then additionally shared, then did one unlock, and - then blocked on an attempt to lock it exclusively again. - Unlocking before every lock fixed the problem. - Note that this introduces a race condition. When the application - wants to convert an exclusive lock into a shared one, it will now - first unlock the file and then lock it shared. A waiting exclusive - lock could step in here. For reasons described in Bug#38133 and - Bug#41124 (Server hangs on Windows with --external-locking after - INSERT...SELECT) and in the review thread at - http://lists.mysql.com/commits/60721 it seems to be the better - option than not to unlock here. - If one day someone notices a way how to do file lock type changes - on Windows without unlocking before taking the new lock, please - change this code accordingly to fix the race condition. - */ - if (!UnlockFileEx(hFile, 0, liLength.LowPart, liLength.HighPart, &ov) && - (GetLastError() != ERROR_NOT_LOCKED)) - goto error; - - if (timeout_sec == WIN_LOCK_INFINITE) - { - if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov)) - DBUG_RETURN(0); - goto error; - } - - dwFlags|= LOCKFILE_FAIL_IMMEDIATELY; - timeout_millis= timeout_sec * 1000; - /* Try lock in a loop, until the lock is acquired or timeout happens */ - for(i= 0; ;i+= WIN_LOCK_SLEEP_MILLIS) - { - if (LockFileEx(hFile, dwFlags, 0, liLength.LowPart, liLength.HighPart, &ov)) - DBUG_RETURN(0); - - if (GetLastError() != ERROR_LOCK_VIOLATION) - goto error; - - if (i >= timeout_millis) - break; - Sleep(WIN_LOCK_SLEEP_MILLIS); - } - - /* timeout */ - errno= EAGAIN; - DBUG_RETURN(-1); - -error: - my_osmaperr(GetLastError()); - DBUG_RETURN(-1); -} -#endif - - - -/* - Lock a part of a file - - RETURN VALUE - 0 Success - -1 An error has occured and 'my_errno' is set - to indicate the actual error code. -*/ - -int my_lock(File fd, int locktype, my_off_t start, my_off_t length, - myf MyFlags) -{ -#ifdef HAVE_FCNTL - int value; - ALARM_VARIABLES; -#endif - - DBUG_ENTER("my_lock"); - DBUG_PRINT("my",("fd: %d Op: %d start: %ld Length: %ld MyFlags: %d", - fd,locktype,(long) start,(long) length,MyFlags)); - if (my_disable_locking) - DBUG_RETURN(0); - -#if defined(_WIN32) - { - int timeout_sec; - if (MyFlags & MY_DONT_WAIT) - timeout_sec= 0; - else - timeout_sec= WIN_LOCK_INFINITE; - - if (win_lock(fd, locktype, start, length, timeout_sec) == 0) - DBUG_RETURN(0); - } -#else -#if defined(HAVE_FCNTL) - { - struct flock lock; - - lock.l_type= (short) locktype; - lock.l_whence= SEEK_SET; - lock.l_start= (off_t) start; - lock.l_len= (off_t) length; - - if (MyFlags & MY_DONT_WAIT) - { - if (fcntl(fd,F_SETLK,&lock) != -1) /* Check if we can lock */ - DBUG_RETURN(0); /* Ok, file locked */ - DBUG_PRINT("info",("Was locked, trying with alarm")); - ALARM_INIT; - while ((value=fcntl(fd,F_SETLKW,&lock)) && ! ALARM_TEST && - errno == EINTR) - { /* Setup again so we don`t miss it */ - ALARM_REINIT; - } - ALARM_END; - if (value != -1) - DBUG_RETURN(0); - if (errno == EINTR) - errno=EAGAIN; - } - else if (fcntl(fd,F_SETLKW,&lock) != -1) /* Wait until a lock */ - DBUG_RETURN(0); - } -#else - if (MyFlags & MY_SEEK_NOT_DONE) - { - if (my_seek(fd,start,MY_SEEK_SET,MYF(MyFlags & ~MY_SEEK_NOT_DONE)) - == MY_FILEPOS_ERROR) - { - /* - If an error has occured in my_seek then we will already - have an error code in my_errno; Just return error code. - */ - DBUG_RETURN(-1); - } - } - if (lockf(fd,locktype,length) != -1) - DBUG_RETURN(0); -#endif /* HAVE_FCNTL */ -#endif /* HAVE_LOCKING */ - - /* We got an error. We don't want EACCES errors */ - my_errno=(errno == EACCES) ? EAGAIN : errno ? errno : -1; - - if (MyFlags & MY_WME) - { - if (locktype == F_UNLCK) - my_error(EE_CANTUNLOCK,MYF(ME_BELL+ME_WAITTANG),my_errno); - else - my_error(EE_CANTLOCK,MYF(ME_BELL+ME_WAITTANG),my_errno); - } - DBUG_PRINT("error",("my_errno: %d (%d)",my_errno,errno)); - DBUG_RETURN(-1); -} /* my_lock */ diff --git a/dep/mysqllite/mysys/my_lockmem.c b/dep/mysqllite/mysys/my_lockmem.c deleted file mode 100644 index a37db6b2089..00000000000 --- a/dep/mysqllite/mysys/my_lockmem.c +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* Alloc a block of locked memory */ - -#include "mysys_priv.h" -#include "mysys_err.h" -#include <my_list.h> - -#ifdef HAVE_MLOCK -#include <sys/mman.h> - -struct st_mem_list -{ - LIST list; - uchar *page; - uint size; -}; - -LIST *mem_list; - -uchar *my_malloc_lock(uint size,myf MyFlags) -{ - int success; - uint pagesize=sysconf(_SC_PAGESIZE); - uchar *ptr; - struct st_mem_list *element; - DBUG_ENTER("my_malloc_lock"); - - size=((size-1) & ~(pagesize-1))+pagesize; - if (!(ptr=memalign(pagesize,size))) - { - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size); - DBUG_RETURN(0); - } - success = mlock((uchar*) ptr,size); - if (success != 0 && geteuid() == 0) - { - DBUG_PRINT("warning",("Failed to lock memory. errno %d\n", - errno)); - fprintf(stderr, "Warning: Failed to lock memory. errno %d\n", - errno); - } - else - { - /* Add block in a list for munlock */ - if (!(element=(struct st_mem_list*) my_malloc(sizeof(*element),MyFlags))) - { - (void) munlock((uchar*) ptr,size); - free(ptr); - DBUG_RETURN(0); - } - element->list.data=(uchar*) element; - element->page=ptr; - element->size=size; - mysql_mutex_lock(&THR_LOCK_malloc); - mem_list=list_add(mem_list,&element->list); - mysql_mutex_unlock(&THR_LOCK_malloc); - } - DBUG_RETURN(ptr); -} - - -void my_free_lock(uchar *ptr) -{ - LIST *list; - struct st_mem_list *element=0; - - mysql_mutex_lock(&THR_LOCK_malloc); - for (list=mem_list ; list ; list=list->next) - { - element=(struct st_mem_list*) list->data; - if (ptr == element->page) - { /* Found locked mem */ - (void) munlock((uchar*) ptr,element->size); - mem_list=list_delete(mem_list,list); - break; - } - } - mysql_mutex_unlock(&THR_LOCK_malloc); - my_free(element); - free(ptr); /* Free even if not locked */ -} - -#endif /* HAVE_MLOCK */ diff --git a/dep/mysqllite/mysys/my_malloc.c b/dep/mysqllite/mysys/my_malloc.c deleted file mode 100644 index fc2dc98c3c5..00000000000 --- a/dep/mysqllite/mysys/my_malloc.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "mysys_priv.h" -#include "mysys_err.h" -#include <m_string.h> - -/** - Allocate a sized block of memory. - - @param size The size of the memory block in bytes. - @param flags Failure action modifiers (bitmasks). - - @return A pointer to the allocated memory block, or NULL on failure. -*/ -void *my_malloc(size_t size, myf my_flags) -{ - void* point; - DBUG_ENTER("my_malloc"); - DBUG_PRINT("my",("size: %lu my_flags: %d", (ulong) size, my_flags)); - - /* Safety */ - if (!size) - size=1; - - point= malloc(size); - DBUG_EXECUTE_IF("simulate_out_of_memory", - { - free(point); - point= NULL; - }); - - if (point == NULL) - { - my_errno=errno; - if (my_flags & MY_FAE) - error_handler_hook=fatal_error_handler_hook; - if (my_flags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_NOREFRESH),size); - DBUG_EXECUTE_IF("simulate_out_of_memory", - DBUG_SET("-d,simulate_out_of_memory");); - if (my_flags & MY_FAE) - exit(1); - } - else if (my_flags & MY_ZEROFILL) - bzero(point, size); - DBUG_PRINT("exit",("ptr: %p", point)); - DBUG_RETURN(point); -} - - -/** - @brief wrapper around realloc() - - @param oldpoint pointer to currently allocated area - @param size new size requested, must be >0 - @param my_flags flags - - @note if size==0 realloc() may return NULL; my_realloc() treats this as an - error which is not the intention of realloc() -*/ -void *my_realloc(void *oldpoint, size_t size, myf my_flags) -{ - void *point; - DBUG_ENTER("my_realloc"); - DBUG_PRINT("my",("ptr: %p size: %lu my_flags: %d", oldpoint, - (ulong) size, my_flags)); - - DBUG_ASSERT(size > 0); - if (!oldpoint && (my_flags & MY_ALLOW_ZERO_PTR)) - DBUG_RETURN(my_malloc(size, my_flags)); -#ifdef USE_HALLOC - if (!(point = malloc(size))) - { - if (my_flags & MY_FREE_ON_ERROR) - my_free(oldpoint); - if (my_flags & MY_HOLD_ON_ERROR) - DBUG_RETURN(oldpoint); - my_errno=errno; - if (my_flags & MY_FAE+MY_WME) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),size); - } - else - { - memcpy(point,oldpoint,size); - free(oldpoint); - } -#else - if ((point= realloc(oldpoint, size)) == NULL) - { - if (my_flags & MY_FREE_ON_ERROR) - my_free(oldpoint); - if (my_flags & MY_HOLD_ON_ERROR) - DBUG_RETURN(oldpoint); - my_errno=errno; - if (my_flags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG), size); - } -#endif - DBUG_PRINT("exit",("ptr: %p", point)); - DBUG_RETURN(point); -} - - -/** - Free memory allocated with my_malloc. - - @remark Relies on free being able to handle a NULL argument. - - @param ptr Pointer to the memory allocated by my_malloc. -*/ -void my_free(void *ptr) -{ - DBUG_ENTER("my_free"); - DBUG_PRINT("my",("ptr: %p", ptr)); - free(ptr); - DBUG_VOID_RETURN; -} - - -void *my_memdup(const void *from, size_t length, myf my_flags) -{ - void *ptr; - if ((ptr= my_malloc(length,my_flags)) != 0) - memcpy(ptr, from, length); - return ptr; -} - - -char *my_strdup(const char *from, myf my_flags) -{ - char *ptr; - size_t length= strlen(from)+1; - if ((ptr= (char*) my_malloc(length, my_flags))) - memcpy(ptr, from, length); - return ptr; -} - - -char *my_strndup(const char *from, size_t length, myf my_flags) -{ - char *ptr; - if ((ptr= (char*) my_malloc(length+1, my_flags))) - { - memcpy(ptr, from, length); - ptr[length]= 0; - } - return ptr; -} - diff --git a/dep/mysqllite/mysys/my_memmem.c b/dep/mysqllite/mysys/my_memmem.c deleted file mode 100644 index c000f14bc66..00000000000 --- a/dep/mysqllite/mysys/my_memmem.c +++ /dev/null @@ -1,83 +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 <my_global.h> -#include <m_string.h> - -/* - my_memmem, port of a GNU extension. - - Returns a pointer to the beginning of the substring, needle, or NULL if the - substring is not found in haystack. -*/ - -void *my_memmem(const void *haystack, size_t haystacklen, - const void *needle, size_t needlelen) -{ - const unsigned char *cursor; - const unsigned char *last_possible_needle_location = - (unsigned char *)haystack + haystacklen - needlelen; - - /* Easy answers */ - if (needlelen > haystacklen) return(NULL); - if (needle == NULL) return(NULL); - if (haystack == NULL) return(NULL); - if (needlelen == 0) return(NULL); - if (haystacklen == 0) return(NULL); - - for (cursor = haystack; cursor <= last_possible_needle_location; cursor++) { - if (memcmp(needle, cursor, needlelen) == 0) { - return((void *) cursor); - } - } - return(NULL); -} - - - -#ifdef MAIN -#include <assert.h> - -int main(int argc, char *argv[]) { - char haystack[10], needle[3]; - - memmove(haystack, "0123456789", 10); - - memmove(needle, "no", 2); - assert(my_memmem(haystack, 10, needle, 2) == NULL); - - memmove(needle, "345", 3); - assert(my_memmem(haystack, 10, needle, 3) != NULL); - - memmove(needle, "789", 3); - assert(my_memmem(haystack, 10, needle, 3) != NULL); - assert(my_memmem(haystack, 9, needle, 3) == NULL); - - memmove(needle, "012", 3); - assert(my_memmem(haystack, 10, needle, 3) != NULL); - assert(my_memmem(NULL, 10, needle, 3) == NULL); - - assert(my_memmem(NULL, 10, needle, 3) == NULL); - assert(my_memmem(haystack, 0, needle, 3) == NULL); - assert(my_memmem(haystack, 10, NULL, 3) == NULL); - assert(my_memmem(haystack, 10, needle, 0) == NULL); - - assert(my_memmem(haystack, 1, needle, 3) == NULL); - - printf("success\n"); - return(0); -} - -#endif diff --git a/dep/mysqllite/mysys/my_mess.c b/dep/mysqllite/mysys/my_mess.c deleted file mode 100644 index 513afe39054..00000000000 --- a/dep/mysqllite/mysys/my_mess.c +++ /dev/null @@ -1,34 +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" - -void my_message_stderr(uint error __attribute__((unused)), - const char *str, myf MyFlags) -{ - DBUG_ENTER("my_message_stderr"); - DBUG_PRINT("enter",("message: %s",str)); - (void) fflush(stdout); - if (MyFlags & ME_BELL) - (void) fputc('\007', stderr); - if (my_progname) - { - (void)fputs(my_progname,stderr); (void)fputs(": ",stderr); - } - (void)fputs(str,stderr); - (void)fputc('\n',stderr); - (void)fflush(stderr); - DBUG_VOID_RETURN; -} diff --git a/dep/mysqllite/mysys/my_mkdir.c b/dep/mysqllite/mysys/my_mkdir.c deleted file mode 100644 index 676c6c1cd51..00000000000 --- a/dep/mysqllite/mysys/my_mkdir.c +++ /dev/null @@ -1,42 +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" -#include <sys/types.h> -#include <sys/stat.h> -#ifdef __WIN__ -#include <direct.h> -#endif - -int my_mkdir(const char *dir, int Flags, myf MyFlags) -{ - DBUG_ENTER("my_dir"); - DBUG_PRINT("enter",("dir: %s",dir)); - -#if defined(__WIN__) - if (mkdir((char*) dir)) -#else - if (mkdir((char*) dir, Flags & my_umask_dir)) -#endif - { - my_errno=errno; - DBUG_PRINT("error",("error %d when creating direcory %s",my_errno,dir)); - if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) - my_error(EE_CANT_MKDIR, MYF(ME_BELL+ME_WAITTANG), dir, my_errno); - DBUG_RETURN(-1); - } - DBUG_RETURN(0); -} diff --git a/dep/mysqllite/mysys/my_mmap.c b/dep/mysqllite/mysys/my_mmap.c deleted file mode 100644 index 82ee1562bc2..00000000000 --- a/dep/mysqllite/mysys/my_mmap.c +++ /dev/null @@ -1,88 +0,0 @@ -/* Copyright (C) 2000-2003 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" - -#ifdef HAVE_SYS_MMAN_H - -/* - system msync() only syncs mmap'ed area to fs cache. - fsync() is required to really sync to disc -*/ -int my_msync(int fd, void *addr, size_t len, int flags) -{ - msync(addr, len, flags); - return my_sync(fd, MYF(0)); -} - -#elif defined(_WIN32) - -static SECURITY_ATTRIBUTES mmap_security_attributes= - {sizeof(SECURITY_ATTRIBUTES), 0, TRUE}; - -void *my_mmap(void *addr, size_t len, int prot, - int flags, File fd, my_off_t offset) -{ - HANDLE hFileMap; - LPVOID ptr; - HANDLE hFile= (HANDLE)my_get_osfhandle(fd); - DBUG_ENTER("my_mmap"); - DBUG_PRINT("mysys", ("map fd: %d", fd)); - - if (hFile == INVALID_HANDLE_VALUE) - DBUG_RETURN(MAP_FAILED); - - hFileMap=CreateFileMapping(hFile, &mmap_security_attributes, - PAGE_READWRITE, 0, (DWORD) len, NULL); - if (hFileMap == 0) - DBUG_RETURN(MAP_FAILED); - - ptr=MapViewOfFile(hFileMap, - prot & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ, - (DWORD)(offset >> 32), (DWORD)offset, len); - - /* - MSDN explicitly states that it's possible to close File Mapping Object - even when a view is not unmapped - then the object will be held open - implicitly until unmap, as every view stores internally a handler of - a corresponding File Mapping Object - */ - CloseHandle(hFileMap); - - if (ptr) - { - DBUG_PRINT("mysys", ("mapped addr: %p", ptr)); - DBUG_RETURN(ptr); - } - - DBUG_RETURN(MAP_FAILED); -} - -int my_munmap(void *addr, size_t len) -{ - DBUG_ENTER("my_munmap"); - DBUG_PRINT("mysys", ("unmap addr: %p", addr)); - DBUG_RETURN(UnmapViewOfFile(addr) ? 0 : -1); -} - -int my_msync(int fd, void *addr, size_t len, int flags) -{ - return FlushViewOfFile(addr, len) ? 0 : -1; -} - -#else -#warning "no mmap!" -#endif - diff --git a/dep/mysqllite/mysys/my_new.cc b/dep/mysqllite/mysys/my_new.cc deleted file mode 100644 index 7da54ffac87..00000000000 --- a/dep/mysqllite/mysys/my_new.cc +++ /dev/null @@ -1,58 +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 */ - -/* - This is a replacement of new/delete operators to be used when compiling - with gcc 3.0.x to avoid including libstdc++ -*/ - -#include "mysys_priv.h" - -#ifdef USE_MYSYS_NEW - -void *operator new (size_t sz) -{ - return (void *) malloc (sz ? sz : 1); -} - -void *operator new[] (size_t sz) -{ - return (void *) malloc (sz ? sz : 1); -} - -void operator delete (void *ptr) -{ - if (ptr) - free(ptr); -} - -void operator delete[] (void *ptr) throw () -{ - if (ptr) - free(ptr); -} - -C_MODE_START - -int __cxa_pure_virtual() -{ - assert(! "Aborted: pure virtual method called."); - return 0; -} - -C_MODE_END - -#endif /* USE_MYSYS_NEW */ - diff --git a/dep/mysqllite/mysys/my_once.c b/dep/mysqllite/mysys/my_once.c deleted file mode 100644 index 32d07802028..00000000000 --- a/dep/mysqllite/mysys/my_once.c +++ /dev/null @@ -1,119 +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 */ - -/* Not MT-SAFE */ - -#include "mysys_priv.h" -#include "my_static.h" -#include "mysys_err.h" -#include <m_string.h> - -/* - Alloc for things we don't nend to free run-time (that only - should be free'd on exit) - - SYNOPSIS - my_once_alloc() - Size - MyFlags - - NOTES - No DBUG_ENTER... here to get smaller dbug-startup -*/ - -void* my_once_alloc(size_t Size, myf MyFlags) -{ - size_t get_size, max_left; - uchar* point; - reg1 USED_MEM *next; - reg2 USED_MEM **prev; - - Size= ALIGN_SIZE(Size); - prev= &my_once_root_block; - max_left=0; - for (next=my_once_root_block ; next && next->left < Size ; next= next->next) - { - if (next->left > max_left) - max_left=next->left; - prev= &next->next; - } - if (! next) - { /* Time to alloc new block */ - get_size= Size+ALIGN_SIZE(sizeof(USED_MEM)); - if (max_left*4 < my_once_extra && get_size < my_once_extra) - get_size=my_once_extra; /* Normal alloc */ - - if ((next = (USED_MEM*) malloc(get_size)) == 0) - { - my_errno=errno; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG),get_size); - return((uchar*) 0); - } - DBUG_PRINT("test",("my_once_malloc %lu byte malloced", (ulong) get_size)); - next->next= 0; - next->size= get_size; - next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); - *prev=next; - } - point= (uchar*) ((char*) next+ (next->size-next->left)); - next->left-= Size; - - if (MyFlags & MY_ZEROFILL) - bzero(point, Size); - return((void*) point); -} /* my_once_alloc */ - - -char *my_once_strdup(const char *src,myf myflags) -{ - size_t len= strlen(src)+1; - uchar *dst= my_once_alloc(len, myflags); - if (dst) - memcpy(dst, src, len); - return (char*) dst; -} - - -void *my_once_memdup(const void *src, size_t len, myf myflags) -{ - uchar *dst= my_once_alloc(len, myflags); - if (dst) - memcpy(dst, src, len); - return dst; -} - - -/* - Deallocate everything that was allocated with my_once_alloc - - SYNOPSIS - my_once_free() -*/ - -void my_once_free(void) -{ - reg1 USED_MEM *next,*old; - DBUG_ENTER("my_once_free"); - - for (next=my_once_root_block ; next ; ) - { - old=next; next= next->next ; - free((uchar*) old); - } - my_once_root_block=0; - - DBUG_VOID_RETURN; -} /* my_once_free */ diff --git a/dep/mysqllite/mysys/my_open.c b/dep/mysqllite/mysys/my_open.c deleted file mode 100644 index 2aef97b3e34..00000000000 --- a/dep/mysqllite/mysys/my_open.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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" -#include <my_dir.h> -#include <errno.h> - - -/* - Open a file - - SYNOPSIS - my_open() - FileName Fully qualified file name - Flags Read | write - MyFlags Special flags - - RETURN VALUE - File descriptor -*/ - -File my_open(const char *FileName, int Flags, myf MyFlags) - /* Path-name of file */ - /* Read | write .. */ - /* Special flags */ -{ - File fd; - DBUG_ENTER("my_open"); - DBUG_PRINT("my",("Name: '%s' Flags: %d MyFlags: %d", - FileName, Flags, MyFlags)); -#if defined(_WIN32) - fd= my_win_open(FileName, Flags); -#elif !defined(NO_OPEN_3) - fd = open(FileName, Flags, my_umask); /* Normal unix */ -#else - fd = open((char *) FileName, Flags); -#endif - - DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_OPEN, - EE_FILENOTFOUND, MyFlags)); -} /* my_open */ - - -/* - Close a file - - SYNOPSIS - my_close() - fd File sescriptor - myf Special Flags - -*/ - -int my_close(File fd, myf MyFlags) -{ - int err; - DBUG_ENTER("my_close"); - DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); - - mysql_mutex_lock(&THR_LOCK_open); -#ifndef _WIN32 - do - { - err= close(fd); - } while (err == -1 && errno == EINTR); -#else - err= my_win_close(fd); -#endif - if (err) - { - DBUG_PRINT("error",("Got error %d on close",err)); - my_errno=errno; - if (MyFlags & (MY_FAE | MY_WME)) - my_error(EE_BADCLOSE, MYF(ME_BELL+ME_WAITTANG),my_filename(fd),errno); - } - if ((uint) fd < my_file_limit && my_file_info[fd].type != UNOPEN) - { - my_free(my_file_info[fd].name); -#if !defined(HAVE_PREAD) && !defined(_WIN32) - mysql_mutex_destroy(&my_file_info[fd].mutex); -#endif - my_file_info[fd].type = UNOPEN; - } - my_file_opened--; - mysql_mutex_unlock(&THR_LOCK_open); - DBUG_RETURN(err); -} /* my_close */ - - -/* - Register file in my_file_info[] - - SYNOPSIS - my_register_filename() - fd File number opened, -1 if error on open - FileName File name - type_file_type How file was created - error_message_number Error message number if caller got error (fd == -1) - MyFlags Flags for my_close() - - RETURN - -1 error - # Filenumber - -*/ - -File my_register_filename(File fd, const char *FileName, enum file_type - type_of_file, uint error_message_number, myf MyFlags) -{ - DBUG_ENTER("my_register_filename"); - if ((int) fd >= MY_FILE_MIN) - { - if ((uint) fd >= my_file_limit) - { -#if !defined(HAVE_PREAD) - my_errno= EMFILE; -#else - thread_safe_increment(my_file_opened,&THR_LOCK_open); - DBUG_RETURN(fd); /* safeguard */ -#endif - } - else - { - mysql_mutex_lock(&THR_LOCK_open); - if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags))) - { - my_file_opened++; - my_file_total_opened++; - my_file_info[fd].type = type_of_file; -#if !defined(HAVE_PREAD) && !defined(_WIN32) - mysql_mutex_init(key_my_file_info_mutex, &my_file_info[fd].mutex, - MY_MUTEX_INIT_FAST); -#endif - mysql_mutex_unlock(&THR_LOCK_open); - DBUG_PRINT("exit",("fd: %d",fd)); - DBUG_RETURN(fd); - } - mysql_mutex_unlock(&THR_LOCK_open); - my_errno= ENOMEM; - } - (void) my_close(fd, MyFlags); - } - else - my_errno= errno; - - DBUG_PRINT("error",("Got error %d on open", my_errno)); - if (MyFlags & (MY_FFNF | MY_FAE | MY_WME)) - { - if (my_errno == EMFILE) - error_message_number= EE_OUT_OF_FILERESOURCES; - DBUG_PRINT("error",("print err: %d",error_message_number)); - my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG), - FileName, my_errno); - } - DBUG_RETURN(-1); -} - - - - -#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/dep/mysqllite/mysys/my_port.c b/dep/mysqllite/mysys/my_port.c deleted file mode 100644 index 9ad333421ca..00000000000 --- a/dep/mysqllite/mysys/my_port.c +++ /dev/null @@ -1,40 +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 */ - -/* - Small functions to make code portable -*/ - -#include "mysys_priv.h" - -#ifdef _AIX - -/* - On AIX, at least with gcc 3.1, the expression - '(double) (ulonglong) var' doesn't always work for big unsigned - integers like '18446744073709551615'. The end result is that the - high bit is simply dropped. (probably bug in gcc optimizations) - Handling the conversion in a sub function seems to work. -*/ - - - -double my_ulonglong2double(unsigned long long nr) -{ - return (double) nr; -} -#endif /* _AIX */ diff --git a/dep/mysqllite/mysys/my_pread.c b/dep/mysqllite/mysys/my_pread.c deleted file mode 100644 index e006360c11b..00000000000 --- a/dep/mysqllite/mysys/my_pread.c +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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" -#include "my_base.h" -#include <m_string.h> -#include <errno.h> -#if defined (HAVE_PREAD) && !defined(_WIN32) -#include <unistd.h> -#endif - - - -/* - Read a chunk of bytes from a file from a given position - - SYNOPSIOS - my_pread() - Filedes File decsriptor - Buffer Buffer to read data into - Count Number of bytes to read - offset Position to read from - MyFlags Flags - - NOTES - This differs from the normal pread() call in that we don't care - to set the position in the file back to the original position - if the system doesn't support pread(). - - RETURN - (size_t) -1 Error - # Number of bytes read -*/ - -size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset, - myf MyFlags) -{ - size_t readbytes; - int error= 0; -#if !defined (HAVE_PREAD) && !defined (_WIN32) - int save_errno; -#endif - DBUG_ENTER("my_pread"); - DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %d", - Filedes, (ulonglong)offset, Buffer, (ulong)Count, MyFlags)); - for (;;) - { - errno= 0; /* Linux, Windows don't reset this on EOF/success */ -#if !defined (HAVE_PREAD) && !defined (_WIN32) - mysql_mutex_lock(&my_file_info[Filedes].mutex); - readbytes= (uint) -1; - error= (lseek(Filedes, offset, MY_SEEK_SET) == (my_off_t) -1 || - (readbytes= read(Filedes, Buffer, Count)) != Count); - save_errno= errno; - mysql_mutex_unlock(&my_file_info[Filedes].mutex); - if (error) - errno= save_errno; -#else -#if defined(_WIN32) - readbytes= my_win_pread(Filedes, Buffer, Count, offset); -#else - readbytes= pread(Filedes, Buffer, Count, offset); -#endif - error= (readbytes != Count); -#endif - if(error) - { - my_errno= errno ? errno : -1; - if (errno == 0 || (readbytes != (size_t) -1 && - (MyFlags & (MY_NABP | MY_FNABP)))) - my_errno= HA_ERR_FILE_TOO_SHORT; - - DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d", - (int) readbytes, (uint) Count,Filedes,my_errno)); - - if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR) - { - DBUG_PRINT("debug", ("my_pread() was interrupted and returned %d", - (int) readbytes)); - continue; /* Interrupted */ - } - - if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) - { - if (readbytes == (size_t) -1) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); - else if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); - } - if (readbytes == (size_t) -1 || (MyFlags & (MY_FNABP | MY_NABP))) - DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ - } - if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Read went ok; Return 0 */ - DBUG_RETURN(readbytes); /* purecov: inspected */ - } -} /* my_pread */ - - -/* - Write a chunk of bytes to a file at a given position - - SYNOPSIOS - my_pwrite() - Filedes File decsriptor - Buffer Buffer to write data from - Count Number of bytes to write - offset Position to write to - MyFlags Flags - - NOTES - This differs from the normal pwrite() call in that we don't care - to set the position in the file back to the original position - if the system doesn't support pwrite() - - RETURN - (size_t) -1 Error - # Number of bytes read -*/ - -size_t my_pwrite(File Filedes, const uchar *Buffer, size_t Count, - my_off_t offset, myf MyFlags) -{ - size_t writtenbytes, written; - uint errors; - - DBUG_ENTER("my_pwrite"); - DBUG_PRINT("my",("fd: %d Seek: %llu Buffer: %p Count: %lu MyFlags: %d", - Filedes, offset, Buffer, (ulong)Count, MyFlags)); - errors= 0; - written= 0; - - for (;;) - { -#if !defined (HAVE_PREAD) && !defined (_WIN32) - int error; - writtenbytes= (size_t) -1; - mysql_mutex_lock(&my_file_info[Filedes].mutex); - error= (lseek(Filedes, offset, MY_SEEK_SET) != (my_off_t) -1 && - (writtenbytes= write(Filedes, Buffer, Count)) == Count); - mysql_mutex_unlock(&my_file_info[Filedes].mutex); - if (error) - break; -#elif defined (_WIN32) - writtenbytes= my_win_pwrite(Filedes, Buffer, Count, offset); -#else - writtenbytes= pwrite(Filedes, Buffer, Count, offset); -#endif - if(writtenbytes == Count) - break; - my_errno= errno; - if (writtenbytes != (size_t) -1) - { - written+= writtenbytes; - Buffer+= writtenbytes; - Count-= writtenbytes; - offset+= writtenbytes; - } - DBUG_PRINT("error",("Write only %u bytes", (uint) writtenbytes)); -#ifndef NO_BACKGROUND - - if (my_thread_var->abort) - MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ - - if ((my_errno == ENOSPC || my_errno == EDQUOT) && - (MyFlags & MY_WAIT_IF_FULL)) - { - wait_for_free_space(my_filename(Filedes), errors); - errors++; - continue; - } - if ((writtenbytes && writtenbytes != (size_t) -1) || my_errno == EINTR) - continue; /* Retry */ -#endif - if (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),my_errno); - } - DBUG_RETURN(MY_FILE_ERROR); /* Error on read */ - } - else - break; /* Return bytes written */ - } - DBUG_EXECUTE_IF("check", my_seek(Filedes, -1, SEEK_SET, MYF(0));); - if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Want only errors */ - DBUG_RETURN(writtenbytes+written); /* purecov: inspected */ -} /* my_pwrite */ diff --git a/dep/mysqllite/mysys/my_pthread.c b/dep/mysqllite/mysys/my_pthread.c deleted file mode 100644 index 150bde3fb33..00000000000 --- a/dep/mysqllite/mysys/my_pthread.c +++ /dev/null @@ -1,469 +0,0 @@ -/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* Functions to get threads more portable */ - -#define DONT_REMAP_PTHREAD_FUNCTIONS - -#include "mysys_priv.h" -#include <signal.h> -#include <m_string.h> -#include <thr_alarm.h> - -#if (defined(__BSD__) || defined(_BSDI_VERSION)) -#define SCHED_POLICY SCHED_RR -#else -#define SCHED_POLICY SCHED_OTHER -#endif - -uint thd_lib_detected= 0; - -/* To allow use of pthread_getspecific with two arguments */ - -#ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC -#undef pthread_getspecific - -void *my_pthread_getspecific_imp(pthread_key_t key) -{ - void *value; - if (pthread_getspecific(key,(void *) &value)) - return 0; - return value; -} -#endif - -/* - Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7 - (and DEC OSF/1 3.2 too) -*/ - -int my_pthread_create_detached=1; - -#if defined(HAVE_NONPOSIX_SIGWAIT) || defined(HAVE_DEC_3_2_THREADS) - -int my_sigwait(const sigset_t *set,int *sig) -{ - int signal=sigwait((sigset_t*) set); - if (signal < 0) - return errno; - *sig=signal; - return 0; -} -#endif - -/* localtime_r for SCO 3.2V4.2 */ - -#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) - -extern mysql_mutex_t LOCK_localtime_r; - -#endif - -#if !defined(HAVE_LOCALTIME_R) -struct tm *localtime_r(const time_t *clock, struct tm *res) -{ - struct tm *tmp; - mysql_mutex_lock(&LOCK_localtime_r); - tmp=localtime(clock); - *res= *tmp; - mysql_mutex_unlock(&LOCK_localtime_r); - return res; -} -#endif - -#if !defined(HAVE_GMTIME_R) -/* - Reentrant version of standard gmtime() function. - Needed on some systems which don't implement it. -*/ - -struct tm *gmtime_r(const time_t *clock, struct tm *res) -{ - struct tm *tmp; - mysql_mutex_lock(&LOCK_localtime_r); - tmp= gmtime(clock); - *res= *tmp; - mysql_mutex_unlock(&LOCK_localtime_r); - return res; -} -#endif - -/**************************************************************************** -** Replacement of sigwait if the system doesn't have one (like BSDI 3.0) -** -** Note: -** This version of sigwait() is assumed to called in a loop so the signalmask -** is permanently modified to reflect the signal set. This is done to get -** a much faster implementation. -** -** This implementation isn't thread safe: It assumes that only one -** thread is using sigwait. -** -** If one later supplies a different signal mask, all old signals that -** was used before are unblocked and set to SIGDFL. -** -** Author: Gary Wisniewski <garyw@spidereye.com.au>, much modified by Monty -****************************************************************************/ - -#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) - -static sigset_t sigwait_set,rev_sigwait_set,px_recd; - -void px_handle_sig(int sig) -{ - sigaddset(&px_recd, sig); -} - - -void sigwait_setup(sigset_t *set) -{ - int i; - struct sigaction sact,sact1; - sigset_t unblock_mask; - - sact.sa_flags = 0; - sact.sa_handler = px_handle_sig; - memcpy(&sact.sa_mask, set, sizeof(*set)); /* handler isn't thread_safe */ - sigemptyset(&unblock_mask); - pthread_sigmask(SIG_UNBLOCK,(sigset_t*) 0,&rev_sigwait_set); - - for (i = 1; i <= sizeof(sigwait_set)*8; i++) - { - if (sigismember(set,i)) - { - sigdelset(&rev_sigwait_set,i); - if (!sigismember(&sigwait_set,i)) - sigaction(i, &sact, (struct sigaction*) 0); - } - else - { - sigdelset(&px_recd,i); /* Don't handle this */ - if (sigismember(&sigwait_set,i)) - { /* Remove the old handler */ - sigaddset(&unblock_mask,i); - sigdelset(&rev_sigwait_set,i); - sact1.sa_flags = 0; - sact1.sa_handler = SIG_DFL; - sigemptyset(&sact1.sa_mask); - sigaction(i, &sact1, 0); - } - } - } - memcpy(&sigwait_set, set, sizeof(*set)); - pthread_sigmask(SIG_BLOCK,(sigset_t*) set,(sigset_t*) 0); - pthread_sigmask(SIG_UNBLOCK,&unblock_mask,(sigset_t*) 0); -} - - -int sigwait(sigset_t *setp, int *sigp) -{ - if (memcmp(setp,&sigwait_set,sizeof(sigwait_set))) - sigwait_setup(setp); /* Init or change of set */ - - for (;;) - { - /* - This is a fast, not 100% portable implementation to find the signal. - Because the handler is blocked there should be at most 1 bit set, but - the specification on this is somewhat shady so we use a set instead a - single variable. - */ - - ulong *ptr= (ulong*) &px_recd; - ulong *end=ptr+sizeof(px_recd)/sizeof(ulong); - - for ( ; ptr != end ; ptr++) - { - if (*ptr) - { - ulong set= *ptr; - int found= (int) ((char*) ptr - (char*) &px_recd)*8+1; - while (!(set & 1)) - { - found++; - set>>=1; - } - *sigp=found; - sigdelset(&px_recd,found); - return 0; - } - } - sigsuspend(&rev_sigwait_set); - } - return 0; -} -#else /* !DONT_USE_SIGSUSPEND */ - -/**************************************************************************** -** Replacement of sigwait if the system doesn't have one (like BSDI 3.0) -** -** Note: -** This version of sigwait() is assumed to called in a loop so the signalmask -** is permanently modified to reflect the signal set. This is done to get -** a much faster implementation. -** -** This implementation uses a extra thread to handle the signals and one -** must always call sigwait() with the same signal mask! -** -** BSDI 3.0 NOTE: -** -** pthread_kill() doesn't work on a thread in a select() or sleep() loop? -** After adding the sleep to sigwait_thread, all signals are checked and -** delivered every second. This isn't that terrible performance vice, but -** someone should report this to BSDI and ask for a fix! -** Another problem is that when the sleep() ends, every select() in other -** threads are interrupted! -****************************************************************************/ - -static sigset_t pending_set; -static bool inited=0; -static pthread_cond_t COND_sigwait; -static pthread_mutex_t LOCK_sigwait; - - -void sigwait_handle_sig(int sig) -{ - pthread_mutex_lock(&LOCK_sigwait); - sigaddset(&pending_set, sig); - pthread_cond_signal(&COND_sigwait); /* inform sigwait() about signal */ - pthread_mutex_unlock(&LOCK_sigwait); -} - -void *sigwait_thread(void *set_arg) -{ - sigset_t *set=(sigset_t*) set_arg; - - int i; - struct sigaction sact; - sact.sa_flags = 0; - sact.sa_handler = sigwait_handle_sig; - memcpy(&sact.sa_mask, set, sizeof(*set)); /* handler isn't thread_safe */ - sigemptyset(&pending_set); - - for (i = 1; i <= sizeof(pending_set)*8; i++) - { - if (sigismember(set,i)) - { - sigaction(i, &sact, (struct sigaction*) 0); - } - } - /* Ensure that init_thr_alarm() is called */ - DBUG_ASSERT(thr_client_alarm); - sigaddset(set, thr_client_alarm); - pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); - alarm_thread=pthread_self(); /* For thr_alarm */ - - for (;;) - { /* Wait for signals */ -#ifdef HAVE_NOT_BROKEN_SELECT - fd_set fd; - FD_ZERO(&fd); - select(0,&fd,0,0,0); -#else - sleep(1); /* Because of broken BSDI */ -#endif - } -} - - -int sigwait(sigset_t *setp, int *sigp) -{ - if (!inited) - { - pthread_attr_t thr_attr; - pthread_t sigwait_thread_id; - inited=1; - sigemptyset(&pending_set); - pthread_mutex_init(&LOCK_sigwait, MY_MUTEX_INIT_FAST); - pthread_cond_init(&COND_sigwait, NULL); - - pthread_attr_init(&thr_attr); - pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); - pthread_attr_setstacksize(&thr_attr,8196); - pthread_create(&sigwait_thread_id, &thr_attr, sigwait_thread, setp); - pthread_attr_destroy(&thr_attr); - } - - pthread_mutex_lock(&LOCK_sigwait); - for (;;) - { - ulong *ptr= (ulong*) &pending_set; - ulong *end=ptr+sizeof(pending_set)/sizeof(ulong); - - for ( ; ptr != end ; ptr++) - { - if (*ptr) - { - ulong set= *ptr; - int found= (int) ((char*) ptr - (char*) &pending_set)*8+1; - while (!(set & 1)) - { - found++; - set>>=1; - } - *sigp=found; - sigdelset(&pending_set,found); - pthread_mutex_unlock(&LOCK_sigwait); - return 0; - } - } - pthread_cond_wait(&COND_sigwait, &LOCK_sigwait); - } - return 0; -} - -#endif /* DONT_USE_SIGSUSPEND */ -#endif /* HAVE_SIGWAIT */ - - -/**************************************************************************** - The following functions fixes that all pthread functions should work - according to latest posix standard -****************************************************************************/ - -/* Undefined wrappers set my_pthread.h so that we call os functions */ -#undef pthread_mutex_init -#undef pthread_mutex_lock -#undef pthread_mutex_unlock -#undef pthread_mutex_destroy -#undef pthread_mutex_wait -#undef pthread_mutex_timedwait -#undef pthread_mutex_trylock -#undef pthread_mutex_t -#undef pthread_cond_init -#undef pthread_cond_wait -#undef pthread_cond_timedwait -#undef pthread_cond_t -#undef pthread_attr_getstacksize - -/***************************************************************************** -** Patches for AIX and DEC OSF/1 3.2 -*****************************************************************************/ - -#if defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) - -#include <netdb.h> - -int my_pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *attr) -{ - int error; - if (!attr) - error=pthread_mutex_init(mp,pthread_mutexattr_default); - else - error=pthread_mutex_init(mp,*attr); - return error; -} - -int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr) -{ - int error; - if (!attr) - error=pthread_cond_init(mp,pthread_condattr_default); - else - error=pthread_cond_init(mp,*attr); - return error; -} - -#endif - - -/***************************************************************************** - Patches for HPUX - We need these because the pthread_mutex.. code returns -1 on error, - instead of the error code. - - Note that currently we only remap pthread_ functions used by MySQL. - If we are depending on the value for some other pthread_xxx functions, - this has to be added here. -****************************************************************************/ - -#if defined(HPUX10) || defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT) - -int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - struct timespec *abstime) -{ - int error=pthread_cond_timedwait(cond, mutex, abstime); - if (error == -1) /* Safety if the lib is fixed */ - { - if (!(error=errno)) - error= ETIMEDOUT; /* Can happen on HPUX */ - } - if (error == EAGAIN) /* Correct errno to Posix */ - error= ETIMEDOUT; - return error; -} -#endif - -#if defined(HPUX10) - -void my_pthread_attr_getstacksize(pthread_attr_t *connection_attrib, - size_t *stack_size) -{ - *stack_size= pthread_attr_getstacksize(*connection_attrib); -} -#endif - - -#ifdef HAVE_POSIX1003_4a_MUTEX -/* - In HP-UX-10.20 and other old Posix 1003.4a Draft 4 implementations - pthread_mutex_trylock returns 1 on success, not 0 like - pthread_mutex_lock - - From the HP-UX-10.20 man page: - RETURN VALUES - If the function fails, errno may be set to one of the following - values: - Return | Error | Description - _______|__________|_________________________________________ - 1 | | Successful completion. - 0 | | The mutex is locked; therefore, it was - | | not acquired. - -1 | [EINVAL] | The value specified by mutex is invalid. - -*/ - -/* - Convert pthread_mutex_trylock to return values according to latest POSIX - - RETURN VALUES - 0 If we are able successfully lock the mutex. - EBUSY Mutex was locked by another thread - # Other error number returned by pthread_mutex_trylock() - (Not likely) -*/ - -int my_pthread_mutex_trylock(pthread_mutex_t *mutex) -{ - int error= pthread_mutex_trylock(mutex); - if (error == 1) - return 0; /* Got lock on mutex */ - if (error == 0) /* Someon else is locking mutex */ - return EBUSY; - if (error == -1) /* Safety if the lib is fixed */ - error= errno; /* Probably invalid parameter */ - return error; -} -#endif /* HAVE_POSIX1003_4a_MUTEX */ - -/* Some help functions */ - -int pthread_dummy(int ret) -{ - return ret; -} diff --git a/dep/mysqllite/mysys/my_quick.c b/dep/mysqllite/mysys/my_quick.c deleted file mode 100644 index b93e7e17224..00000000000 --- a/dep/mysqllite/mysys/my_quick.c +++ /dev/null @@ -1,81 +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 */ - -/* Quicker interface to read & write. Used with my_nosys.h */ - -#include "mysys_priv.h" -#include "my_nosys.h" - - -#ifdef _WIN32 -extern size_t my_win_read(File Filedes,uchar *Buffer,size_t Count); -#endif - -size_t my_quick_read(File Filedes,uchar *Buffer,size_t Count,myf MyFlags) -{ - size_t readbytes; -#ifdef _WIN32 - readbytes= my_win_read(Filedes, Buffer, Count); -#else - readbytes= read(Filedes, Buffer, Count); -#endif - if(readbytes != Count) - { -#ifndef DBUG_OFF - if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR) - { - DBUG_PRINT("error", ("my_quick_read() was interrupted and returned %d" - ". This function does not retry the read!", - (int) readbytes)); - } -#endif - my_errno=errno; - return readbytes; - } - return (MyFlags & (MY_NABP | MY_FNABP)) ? 0 : readbytes; -} - - - -size_t my_quick_write(File Filedes, const uchar *Buffer, size_t Count) -{ -#ifdef _WIN32 - return my_win_write(Filedes, Buffer, Count); -#else - -#ifndef DBUG_OFF - size_t writtenbytes; -#endif - - if (( -#ifndef DBUG_OFF - writtenbytes = -#endif - (size_t) write(Filedes,Buffer,Count)) != Count) - { -#ifndef DBUG_OFF - if ((writtenbytes == 0 || writtenbytes == (size_t) -1) && errno == EINTR) - { - DBUG_PRINT("error", ("my_quick_write() was interrupted and returned %d" - ". This function does not retry the write!", - (int) writtenbytes)); - } -#endif - my_errno=errno; - return (size_t) -1; - } - return 0; -#endif -} diff --git a/dep/mysqllite/mysys/my_rdtsc.c b/dep/mysqllite/mysys/my_rdtsc.c deleted file mode 100644 index 2afe3ec31dd..00000000000 --- a/dep/mysqllite/mysys/my_rdtsc.c +++ /dev/null @@ -1,962 +0,0 @@ -/* Copyright (C) 2008-2010 Sun Microsystems, Inc - - 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 */ - -/* - rdtsc3 -- multi-platform timer code - pgulutzan@mysql.com, 2005-08-29 - modified 2008-11-02 - - Functions: - - my_timer_cycles ulonglong cycles - my_timer_nanoseconds ulonglong nanoseconds - my_timer_microseconds ulonglong "microseconds" - my_timer_milliseconds ulonglong milliseconds - my_timer_ticks ulonglong ticks - my_timer_init initialization / test - - We'll call the first 5 functions (the ones that return - a ulonglong) "my_timer_xxx" functions. - Each my_timer_xxx function returns a 64-bit timing value - since an arbitrary 'epoch' start. Since the only purpose - is to determine elapsed times, wall-clock time-of-day - is not known and not relevant. - - The my_timer_init function is necessary for initializing. - It returns information (underlying routine name, - frequency, resolution, overhead) about all my_timer_xxx - functions. A program should call my_timer_init once, - use the information to decide what my_timer_xxx function - to use, and subsequently call that function by function - pointer. - - A typical use would be: - my_timer_init() ... once, at program start - ... - time1= my_timer_xxx() ... time before start - [code that's timed] - time2= my_timer_xxx() ... time after end - elapsed_time= (time2 - time1) - overhead -*/ - -#include "my_global.h" -#include "my_rdtsc.h" - -#if defined(_WIN32) -#include <stdio.h> -#include "windows.h" -#else -#include <stdio.h> -#endif - -#if !defined(_WIN32) -#if TIME_WITH_SYS_TIME -#include <sys/time.h> -#include <time.h> /* for clock_gettime */ -#else -#if HAVE_SYS_TIME_H -#include <sys/time.h> -#elif defined(HAVE_TIME_H) -#include <time.h> -#endif -#endif -#endif - -#if defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL) -#include <asm/msr.h> /* for rdtscll */ -#endif - -#if defined(HAVE_SYS_TIMEB_H) && defined(HAVE_FTIME) -#include <sys/timeb.h> /* for ftime */ -#endif - -#if defined(HAVE_SYS_TIMES_H) && defined(HAVE_TIMES) -#include <sys/times.h> /* for times */ -#endif - -#if defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) -#include <ia64intrin.h> /* for __GetReg */ -#endif - -#if defined(__APPLE__) && defined(__MACH__) -#include <mach/mach_time.h> -#endif - -#if defined(__SUNPRO_CC) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7) -extern "C" ulonglong my_timer_cycles_il_sparc64(); -#elif defined(__SUNPRO_CC) && defined(_ILP32) && !defined(__SunOS_5_7) -extern "C" ulonglong my_timer_cycles_il_sparc32(); -#elif defined(__SUNPRO_CC) && defined(__i386) && defined(_ILP32) -extern "C" ulonglong my_timer_cycles_il_i386(); -#elif defined(__SUNPRO_CC) && defined(__x86_64) && defined(_LP64) -extern "C" ulonglong my_timer_cycles_il_x86_64(); -#elif defined(__SUNPRO_C) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7) -ulonglong my_timer_cycles_il_sparc64(); -#elif defined(__SUNPRO_C) && defined(_ILP32) && !defined(__SunOS_5_7) -ulonglong my_timer_cycles_il_sparc32(); -#elif defined(__SUNPRO_C) && defined(__i386) && defined(_ILP32) -ulonglong my_timer_cycles_il_i386(); -#elif defined(__SUNPRO_C) && defined(__x86_64) && defined(_LP64) -ulonglong my_timer_cycles_il_x86_64(); -#endif - -#if defined(__INTEL_COMPILER) -/* - icc warning #1011 is: - missing return statement at end of non-void function -*/ -#pragma warning (disable:1011) -#endif - -/* - For cycles, we depend on RDTSC for x86 platforms, - or on time buffer (which is not really a cycle count - but a separate counter with less than nanosecond - resolution) for most PowerPC platforms, or on - gethrtime which is okay for hpux and solaris, or on - clock_gettime(CLOCK_SGI_CYCLE) for Irix platforms, - or on read_real_time for aix platforms. There is - nothing for Alpha platforms, they would be tricky. -*/ - -ulonglong my_timer_cycles(void) -{ -#if defined(__GNUC__) && defined(__i386__) - /* This works much better if compiled with "gcc -O3". */ - ulonglong result; - __asm__ __volatile__ ("rdtsc" : "=A" (result)); - return result; -#elif defined(__SUNPRO_C) && defined(__i386) - __asm("rdtsc"); -#elif defined(__GNUC__) && defined(__x86_64__) - ulonglong result; - __asm__ __volatile__ ("rdtsc\n\t" \ - "shlq $32,%%rdx\n\t" \ - "orq %%rdx,%%rax" - : "=a" (result) :: "%edx"); - return result; -#elif defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL) - { - ulonglong result; - rdtscll(result); - return result; - } -#elif defined(_WIN32) && defined(_M_IX86) - __asm {rdtsc}; -#elif defined(_WIN64) && defined(_M_X64) - /* For 64-bit Windows: unsigned __int64 __rdtsc(); */ - return __rdtsc(); -#elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) - return (ulonglong) __getReg(_IA64_REG_AR_ITC); /* (3116) */ -#elif defined(__GNUC__) && defined(__ia64__) - { - ulonglong result; - __asm __volatile__ ("mov %0=ar.itc" : "=r" (result)); - return result; - } -#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (defined(__64BIT__) || defined(_ARCH_PPC64)) - { - ulonglong result; - __asm __volatile__ ("mftb %0" : "=r" (result)); - return result; - } -#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (!defined(__64BIT__) && !defined(_ARCH_PPC64)) - { - /* - mftbu means "move from time-buffer-upper to result". - The loop is saying: x1=upper, x2=lower, x3=upper, - if x1!=x3 there was an overflow so repeat. - */ - unsigned int x1, x2, x3; - ulonglong result; - for (;;) - { - __asm __volatile__ ( "mftbu %0" : "=r"(x1) ); - __asm __volatile__ ( "mftb %0" : "=r"(x2) ); - __asm __volatile__ ( "mftbu %0" : "=r"(x3) ); - if (x1 == x3) break; - } - result = x1; - return ( result << 32 ) | x2; - } -#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7) - return (my_timer_cycles_il_sparc64()); -#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(_ILP32) && !defined(__SunOS_5_7) - return (my_timer_cycles_il_sparc32()); -#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__i386) && defined(_ILP32) - /* This is probably redundant for __SUNPRO_C. */ - return (my_timer_cycles_il_i386()); -#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__x86_64) && defined(_LP64) - return (my_timer_cycles_il_x86_64()); -#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) && (__GNUC__>2) - { - ulonglong result; - __asm __volatile__ ("rd %%tick,%0" : "=r" (result)); - return result; - } -#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) && (__GNUC__>2) - { - union { - ulonglong wholeresult; - struct { - ulong high; - ulong low; - } splitresult; - } result; - __asm __volatile__ ("rd %%tick,%1; srlx %1,32,%0" : "=r" (result.splitresult.high), "=r" (result.splitresult.low)); - return result.wholeresult; - } -#elif defined(__sgi) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_SGI_CYCLE) - { - struct timespec tp; - clock_gettime(CLOCK_SGI_CYCLE, &tp); - return (ulonglong) tp.tv_sec * 1000000000 + (ulonglong) tp.tv_nsec; - } -#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) - /* gethrtime may appear as either cycle or nanosecond counter */ - return (ulonglong) gethrtime(); -#else - return 0; -#endif -} - -#if defined(__INTEL_COMPILER) -/* re-enable warning#1011 which was only for my_timer_cycles() */ -/* There may be an icc bug which means we must leave disabled. */ -#pragma warning (default:1011) -#endif - -/* - For nanoseconds, most platforms have nothing available that - (a) doesn't require bringing in a 40-kb librt.so library - (b) really has nanosecond resolution. -*/ - -ulonglong my_timer_nanoseconds(void) -{ -#if defined(HAVE_READ_REAL_TIME) - { - timebasestruct_t tr; - read_real_time(&tr, TIMEBASE_SZ); - return (ulonglong) tr.tb_high * 1000000000 + (ulonglong) tr.tb_low; - } -#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) - /* SunOS 5.10+, Solaris, HP-UX: hrtime_t gethrtime(void) */ - return (ulonglong) gethrtime(); -#elif defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) - { - struct timespec tp; - clock_gettime(CLOCK_REALTIME, &tp); - return (ulonglong) tp.tv_sec * 1000000000 + (ulonglong) tp.tv_nsec; - } -#elif defined(__APPLE__) && defined(__MACH__) - { - ulonglong tm; - static mach_timebase_info_data_t timebase_info= {0,0}; - if (timebase_info.denom == 0) - (void) mach_timebase_info(&timebase_info); - tm= mach_absolute_time(); - return (tm * timebase_info.numer) / timebase_info.denom; - } -#else - return 0; -#endif -} - -/* - For microseconds, gettimeofday() is available on - almost all platforms. On Windows we use - QueryPerformanceCounter which will usually tick over - 3.5 million times per second, and we don't throw - away the extra precision. (On Windows Server 2003 - the frequency is same as the cycle frequency.) -*/ - -ulonglong my_timer_microseconds(void) -{ -#if defined(HAVE_GETTIMEOFDAY) - { - static ulonglong last_value= 0; - struct timeval tv; - if (gettimeofday(&tv, NULL) == 0) - last_value= (ulonglong) tv.tv_sec * 1000000 + (ulonglong) tv.tv_usec; - else - { - /* - There are reports that gettimeofday(2) can have intermittent failures - on some platform, see for example Bug#36819. - We are not trying again or looping, just returning the best value possible - under the circumstances ... - */ - last_value++; - } - return last_value; - } -#elif defined(_WIN32) - { - /* QueryPerformanceCounter usually works with about 1/3 microsecond. */ - LARGE_INTEGER t_cnt; - - QueryPerformanceCounter(&t_cnt); - return (ulonglong) t_cnt.QuadPart; - } -#else - return 0; -#endif -} - -/* - For milliseconds, we use ftime() if it's supported - or time()*1000 if it's not. With modern versions of - Windows and with HP Itanium, resolution is 10-15 - milliseconds. -*/ - -ulonglong my_timer_milliseconds(void) -{ -#if defined(HAVE_SYS_TIMEB_H) && defined(HAVE_FTIME) - /* ftime() is obsolete but maybe the platform is old */ - struct timeb ft; - ftime(&ft); - return (ulonglong)ft.time * 1000 + (ulonglong)ft.millitm; -#elif defined(HAVE_TIME) - return (ulonglong) time(NULL) * 1000; -#elif defined(_WIN32) - FILETIME ft; - GetSystemTimeAsFileTime( &ft ); - return ((ulonglong)ft.dwLowDateTime + - (((ulonglong)ft.dwHighDateTime) << 32))/10000; -#else - return 0; -#endif -} - -/* - For ticks, which we handle with times(), the frequency - is usually 100/second and the overhead is surprisingly - bad, sometimes even worse than gettimeofday's overhead. -*/ - -ulonglong my_timer_ticks(void) -{ -#if defined(HAVE_SYS_TIMES_H) && defined(HAVE_TIMES) - { - struct tms times_buf; - return (ulonglong) times(×_buf); - } -#elif defined(_WIN32) - return (ulonglong) GetTickCount(); -#else - return 0; -#endif -} - -/* - The my_timer_init() function and its sub-functions - have several loops which call timers. If there's - something wrong with a timer -- which has never - happened in tests -- we want the loop to end after - an arbitrary number of iterations, and my_timer_info - will show a discouraging result. The arbitrary - number is 1,000,000. -*/ -#define MY_TIMER_ITERATIONS 1000000 - -/* - Calculate overhead. Called from my_timer_init(). - Usually best_timer_overhead = cycles.overhead or - nanoseconds.overhead, so returned amount is in - cycles or nanoseconds. We repeat the calculation - ten times, so that we can disregard effects of - caching or interrupts. Result is quite consistent - for cycles, at least. But remember it's a minimum. -*/ - -static void my_timer_init_overhead(ulonglong *overhead, - ulonglong (*cycle_timer)(void), - ulonglong (*this_timer)(void), - ulonglong best_timer_overhead) -{ - ulonglong time1, time2; - int i; - - /* *overhead, least of 20 calculations - cycles.overhead */ - for (i= 0, *overhead= 1000000000; i < 20; ++i) - { - time1= cycle_timer(); - this_timer(); /* rather than 'time_tmp= timer();' */ - time2= cycle_timer() - time1; - if (*overhead > time2) - *overhead= time2; - } - *overhead-= best_timer_overhead; -} - -/* - Calculate Resolution. Called from my_timer_init(). - If a timer goes up by jumps, e.g. 1050, 1075, 1100, ... - then the best resolution is the minimum jump, e.g. 25. - If it's always divisible by 1000 then it's just a - result of multiplication of a lower-precision timer - result, e.g. nanoseconds are often microseconds * 1000. - If the minimum jump is less than an arbitrary passed - figure (a guess based on maximum overhead * 2), ignore. - Usually we end up with nanoseconds = 1 because it's too - hard to detect anything <= 100 nanoseconds. - Often GetTickCount() has resolution = 15. - We don't check with ticks because they take too long. -*/ -static ulonglong my_timer_init_resolution(ulonglong (*this_timer)(void), - ulonglong overhead_times_2) -{ - ulonglong time1, time2; - ulonglong best_jump; - int i, jumps, divisible_by_1000, divisible_by_1000000; - - divisible_by_1000= divisible_by_1000000= 0; - best_jump= 1000000; - for (i= jumps= 0; jumps < 3 && i < MY_TIMER_ITERATIONS * 10; ++i) - { - time1= this_timer(); - time2= this_timer(); - time2-= time1; - if (time2) - { - ++jumps; - if (!(time2 % 1000)) - { - ++divisible_by_1000; - if (!(time2 % 1000000)) - ++divisible_by_1000000; - } - if (best_jump > time2) - best_jump= time2; - /* For milliseconds, one jump is enough. */ - if (overhead_times_2 == 0) - break; - } - } - if (jumps == 3) - { - if (jumps == divisible_by_1000000) - return 1000000; - if (jumps == divisible_by_1000) - return 1000; - } - if (best_jump > overhead_times_2) - return best_jump; - return 1; -} - -/* - Calculate cycle frequency by seeing how many cycles pass - in a 200-microsecond period. I tried with 10-microsecond - periods originally, and the result was often very wrong. -*/ - -static ulonglong my_timer_init_frequency(MY_TIMER_INFO *mti) -{ - int i; - ulonglong time1, time2, time3, time4; - time1= my_timer_cycles(); - time2= my_timer_microseconds(); - time3= time2; /* Avoids a Microsoft/IBM compiler warning */ - for (i= 0; i < MY_TIMER_ITERATIONS; ++i) - { - time3= my_timer_microseconds(); - if (time3 - time2 > 200) break; - } - time4= my_timer_cycles() - mti->cycles.overhead; - time4-= mti->microseconds.overhead; - return (mti->microseconds.frequency * (time4 - time1)) / (time3 - time2); -} - -/* - Call my_timer_init before the first call to my_timer_xxx(). - If something must be initialized, it happens here. - Set: what routine is being used e.g. "asm_x86" - Set: function, overhead, actual frequency, resolution. -*/ - -void my_timer_init(MY_TIMER_INFO *mti) -{ - ulonglong (*best_timer)(void); - ulonglong best_timer_overhead; - ulonglong time1, time2; - int i; - - /* cycles */ - mti->cycles.frequency= 1000000000; -#if defined(__GNUC__) && defined(__i386__) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86; -#elif defined(__SUNPRO_C) && defined(__i386) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86; -#elif defined(__GNUC__) && defined(__x86_64__) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86_64; -#elif defined(HAVE_ASM_MSR_H) && defined(HAVE_RDTSCLL) - mti->cycles.routine= MY_TIMER_ROUTINE_RDTSCLL; -#elif defined(_WIN32) && defined(_M_IX86) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_X86_WIN; -#elif defined(_WIN64) && defined(_M_X64) - mti->cycles.routine= MY_TIMER_ROUTINE_RDTSC; -#elif defined(__INTEL_COMPILER) && defined(__ia64__) && defined(HAVE_IA64INTRIN_H) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_IA64; -#elif defined(__GNUC__) && defined(__ia64__) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_IA64; -#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (defined(__64BIT__) || defined(_ARCH_PPC64)) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_PPC64; -#elif defined(__GNUC__) && (defined(__powerpc__) || defined(__POWERPC__) || (defined(_POWER) && defined(_AIX52))) && (!defined(__64BIT__) && !defined(_ARCH_PPC64)) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_PPC; -#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__sparcv9) && defined(_LP64) && !defined(__SunOS_5_7) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC64; -#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(_ILP32) && !defined(__SunOS_5_7) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_SPARC32; -#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__i386) && defined(_ILP32) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_I386; -#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) && defined(__x86_64) && defined(_LP64) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_SUNPRO_X86_64; -#elif defined(__GNUC__) && defined(__sparcv9) && defined(_LP64) && (__GNUC__>2) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_GCC_SPARC64; -#elif defined(__GNUC__) && defined(__sparc__) && !defined(_LP64) && (__GNUC__>2) - mti->cycles.routine= MY_TIMER_ROUTINE_ASM_GCC_SPARC32; -#elif defined(__sgi) && defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_SGI_CYCLE) - mti->cycles.routine= MY_TIMER_ROUTINE_SGI_CYCLE; -#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) - mti->cycles.routine= MY_TIMER_ROUTINE_GETHRTIME; -#else - mti->cycles.routine= 0; -#endif - - if (!mti->cycles.routine || !my_timer_cycles()) - { - mti->cycles.routine= 0; - mti->cycles.resolution= 0; - mti->cycles.frequency= 0; - mti->cycles.overhead= 0; - } - - /* nanoseconds */ - mti->nanoseconds.frequency= 1000000000; /* initial assumption */ -#if defined(HAVE_READ_REAL_TIME) - mti->nanoseconds.routine= MY_TIMER_ROUTINE_READ_REAL_TIME; -#elif defined(HAVE_SYS_TIMES_H) && defined(HAVE_GETHRTIME) - mti->nanoseconds.routine= MY_TIMER_ROUTINE_GETHRTIME; -#elif defined(HAVE_CLOCK_GETTIME) - mti->nanoseconds.routine= MY_TIMER_ROUTINE_CLOCK_GETTIME; -#elif defined(__APPLE__) && defined(__MACH__) - mti->nanoseconds.routine= MY_TIMER_ROUTINE_MACH_ABSOLUTE_TIME; -#else - mti->nanoseconds.routine= 0; -#endif - if (!mti->nanoseconds.routine || !my_timer_nanoseconds()) - { - mti->nanoseconds.routine= 0; - mti->nanoseconds.resolution= 0; - mti->nanoseconds.frequency= 0; - mti->nanoseconds.overhead= 0; - } - - /* microseconds */ - mti->microseconds.frequency= 1000000; /* initial assumption */ -#if defined(HAVE_GETTIMEOFDAY) - mti->microseconds.routine= MY_TIMER_ROUTINE_GETTIMEOFDAY; -#elif defined(_WIN32) - { - LARGE_INTEGER li; - /* Windows: typical frequency = 3579545, actually 1/3 microsecond. */ - if (!QueryPerformanceFrequency(&li)) - mti->microseconds.routine= 0; - else - { - mti->microseconds.frequency= li.QuadPart; - mti->microseconds.routine= MY_TIMER_ROUTINE_QUERYPERFORMANCECOUNTER; - } - } -#else - mti->microseconds.routine= 0; -#endif - if (!mti->microseconds.routine || !my_timer_microseconds()) - { - mti->microseconds.routine= 0; - mti->microseconds.resolution= 0; - mti->microseconds.frequency= 0; - mti->microseconds.overhead= 0; - } - - /* milliseconds */ - mti->milliseconds.frequency= 1000; /* initial assumption */ -#if defined(HAVE_SYS_TIMEB_H) && defined(HAVE_FTIME) - mti->milliseconds.routine= MY_TIMER_ROUTINE_FTIME; -#elif defined(_WIN32) - mti->milliseconds.routine= MY_TIMER_ROUTINE_GETSYSTEMTIMEASFILETIME; -#elif defined(HAVE_TIME) - mti->milliseconds.routine= MY_TIMER_ROUTINE_TIME; -#else - mti->milliseconds.routine= 0; -#endif - if (!mti->milliseconds.routine || !my_timer_milliseconds()) - { - mti->milliseconds.routine= 0; - mti->milliseconds.resolution= 0; - mti->milliseconds.frequency= 0; - mti->milliseconds.overhead= 0; - } - - /* ticks */ - mti->ticks.frequency= 100; /* permanent assumption */ -#if defined(HAVE_SYS_TIMES_H) && defined(HAVE_TIMES) - mti->ticks.routine= MY_TIMER_ROUTINE_TIMES; -#elif defined(_WIN32) - mti->ticks.routine= MY_TIMER_ROUTINE_GETTICKCOUNT; -#else - mti->ticks.routine= 0; -#endif - if (!mti->ticks.routine || !my_timer_ticks()) - { - mti->ticks.routine= 0; - mti->ticks.resolution= 0; - mti->ticks.frequency= 0; - mti->ticks.overhead= 0; - } - - /* - Calculate overhead in terms of the timer that - gives the best resolution: cycles or nanoseconds. - I doubt it ever will be as bad as microseconds. - */ - if (mti->cycles.routine) - best_timer= &my_timer_cycles; - else - { - if (mti->nanoseconds.routine) - { - best_timer= &my_timer_nanoseconds; - } - else - best_timer= &my_timer_microseconds; - } - - /* best_timer_overhead = least of 20 calculations */ - for (i= 0, best_timer_overhead= 1000000000; i < 20; ++i) - { - time1= best_timer(); - time2= best_timer() - time1; - if (best_timer_overhead > time2) - best_timer_overhead= time2; - } - if (mti->cycles.routine) - my_timer_init_overhead(&mti->cycles.overhead, - best_timer, - &my_timer_cycles, - best_timer_overhead); - if (mti->nanoseconds.routine) - my_timer_init_overhead(&mti->nanoseconds.overhead, - best_timer, - &my_timer_nanoseconds, - best_timer_overhead); - if (mti->microseconds.routine) - my_timer_init_overhead(&mti->microseconds.overhead, - best_timer, - &my_timer_microseconds, - best_timer_overhead); - if (mti->milliseconds.routine) - my_timer_init_overhead(&mti->milliseconds.overhead, - best_timer, - &my_timer_milliseconds, - best_timer_overhead); - if (mti->ticks.routine) - my_timer_init_overhead(&mti->ticks.overhead, - best_timer, - &my_timer_ticks, - best_timer_overhead); - -/* - Calculate resolution for nanoseconds or microseconds - or milliseconds, by seeing if it's always divisible - by 1000, and by noticing how much jumping occurs. - For ticks, just assume the resolution is 1. -*/ - if (mti->cycles.routine) - mti->cycles.resolution= 1; - if (mti->nanoseconds.routine) - mti->nanoseconds.resolution= - my_timer_init_resolution(&my_timer_nanoseconds, 20000); - if (mti->microseconds.routine) - mti->microseconds.resolution= - my_timer_init_resolution(&my_timer_microseconds, 20); - if (mti->milliseconds.routine) - { - if (mti->milliseconds.routine == MY_TIMER_ROUTINE_TIME) - mti->milliseconds.resolution= 1000; - else - mti->milliseconds.resolution= - my_timer_init_resolution(&my_timer_milliseconds, 0); - } - if (mti->ticks.routine) - mti->ticks.resolution= 1; - -/* - Calculate cycles frequency, - if we have both a cycles routine and a microseconds routine. - In tests, this usually results in a figure within 2% of - what "cat /proc/cpuinfo" says. - If the microseconds routine is QueryPerformanceCounter - (i.e. it's Windows), and the microseconds frequency is > - 500,000,000 (i.e. it's Windows Server so it uses RDTSC) - and the microseconds resolution is > 100 (i.e. dreadful), - then calculate cycles frequency = microseconds frequency. -*/ - if (mti->cycles.routine - && mti->microseconds.routine) - { - if (mti->microseconds.routine == - MY_TIMER_ROUTINE_QUERYPERFORMANCECOUNTER - && mti->microseconds.frequency > 500000000 - && mti->microseconds.resolution > 100) - mti->cycles.frequency= mti->microseconds.frequency; - else - { - ulonglong time1, time2; - time1= my_timer_init_frequency(mti); - /* Repeat once in case there was an interruption. */ - time2= my_timer_init_frequency(mti); - if (time1 < time2) mti->cycles.frequency= time1; - else mti->cycles.frequency= time2; - } - } - -/* - Calculate milliseconds frequency = - (cycles-frequency/#-of-cycles) * #-of-milliseconds, - if we have both a milliseconds routine and a cycles - routine. - This will be inaccurate if milliseconds resolution > 1. - This is probably only useful when testing new platforms. -*/ - if (mti->milliseconds.routine - && mti->milliseconds.resolution < 1000 - && mti->microseconds.routine - && mti->cycles.routine) - { - int i; - ulonglong time1, time2, time3, time4; - time1= my_timer_cycles(); - time2= my_timer_milliseconds(); - time3= time2; /* Avoids a Microsoft/IBM compiler warning */ - for (i= 0; i < MY_TIMER_ITERATIONS * 1000; ++i) - { - time3= my_timer_milliseconds(); - if (time3 - time2 > 10) break; - } - time4= my_timer_cycles(); - mti->milliseconds.frequency= - (mti->cycles.frequency * (time3 - time2)) / (time4 - time1); - } - -/* - Calculate ticks.frequency = - (cycles-frequency/#-of-cycles * #-of-ticks, - if we have both a ticks routine and a cycles - routine, - This is probably only useful when testing new platforms. -*/ - if (mti->ticks.routine - && mti->microseconds.routine - && mti->cycles.routine) - { - int i; - ulonglong time1, time2, time3, time4; - time1= my_timer_cycles(); - time2= my_timer_ticks(); - time3= time2; /* Avoids a Microsoft/IBM compiler warning */ - for (i= 0; i < MY_TIMER_ITERATIONS * 1000; ++i) - { - time3= my_timer_ticks(); - if (time3 - time2 > 10) break; - } - time4= my_timer_cycles(); - mti->ticks.frequency= - (mti->cycles.frequency * (time3 - time2)) / (time4 - time1); - } -} - -/* - Additional Comments - ------------------- - - This is for timing, i.e. finding out how long a piece of code - takes. If you want time of day matching a wall clock, the - my_timer_xxx functions won't help you. - - The best timer is the one with highest frequency, lowest - overhead, and resolution=1. The my_timer_info() routine will tell - you at runtime which timer that is. Usually it will be - my_timer_cycles() but be aware that, although it's best, - it has possible flaws and dangers. Depending on platform: - - The frequency might change. We don't test for this. It - happens on laptops for power saving, and on blade servers - for avoiding overheating. - - The overhead that my_timer_init() returns is the minimum. - In fact it could be slightly greater because of caching or - because you call the routine by address, as recommended. - It could be hugely greater if there's an interrupt. - - The x86 cycle counter, RDTSC doesn't "serialize". That is, - if there is out-of-order execution, rdtsc might be processed - after an instruction that logically follows it. - (We could force serialization, but that would be slower.) - - It is possible to set a flag which renders RDTSC - inoperative. Somebody responsible for the kernel - of the operating system would have to make this - decision. For the platforms we've tested with, there's - no such problem. - - With a multi-processor arrangement, it's possible - to get the cycle count from one processor in - thread X, and the cycle count from another processor - in thread Y. They may not always be in synch. - - You can't depend on a cycle counter being available for - all platforms. On Alphas, the - cycle counter is only 32-bit, so it would overflow quickly, - so we don't bother with it. On platforms that we haven't - tested, there might be some if/endif combination that we - didn't expect, or some assembler routine that we didn't - supply. - - The recommended way to use the timer routines is: - 1. Somewhere near the beginning of the program, call - my_timer_init(). This should only be necessary once, - although you can call it again if you think that the - frequency has changed. - 2. Determine the best timer based on frequency, resolution, - overhead -- all things that my_timer_init() returns. - Preserve the address of the timer and the my_timer_into - results in an easily-accessible place. - 3. Instrument the code section that you're monitoring, thus: - time1= my_timer_xxx(); - Instrumented code; - time2= my_timer_xxx(); - elapsed_time= (time2 - time1) - overhead; - If the timer is always on, then overhead is always there, - so don't subtract it. - 4. Save the elapsed time, or add it to a totaller. - 5. When all timing processes are complete, transfer the - saved / totalled elapsed time to permanent storage. - Optionally you can convert cycles to microseconds at - this point. (Don't do so every time you calculate - elapsed_time! That would waste time and lose precision!) - For converting cycles to microseconds, use the frequency - that my_timer_init() returns. You'll also need to convert - if the my_timer_microseconds() function is the Windows - function QueryPerformanceCounter(), since that's sometimes - a counter with precision slightly better than microseconds. - - Since we recommend calls by function pointer, we supply - no inline functions. - - Some comments on the many candidate routines for timing ... - - clock() -- We don't use because it would overflow frequently. - - clock_gettime() -- In tests, clock_gettime often had - resolution = 1000. - - ftime() -- A "man ftime" says: "This function is obsolete. - Don't use it." On every platform that we tested, if ftime() - was available, then so was gettimeofday(), and gettimeofday() - overhead was always at least as good as ftime() overhead. - - gettimeofday() -- available on most platforms, though not - on Windows. There is a hardware timer (sometimes a Programmable - Interrupt Timer or "PIT") (sometimes a "HPET") used for - interrupt generation. When it interrupts (a "tick" or "jiffy", - typically 1 centisecond) it sets xtime. For gettimeofday, a - Linux kernel routine usually gets xtime and then gets rdtsc - to get elapsed nanoseconds since the last tick. On Red Hat - Enterprise Linux 3, there was once a bug which caused the - resolution to be 1000, i.e. one centisecond. We never check - for time-zone change. - - getnstimeofday() -- something to watch for in future Linux - - do_gettimeofday() -- exists on Linux but not for "userland" - - get_cycles() -- a multi-platform function, worth watching - in future Linux versions. But we found platform-specific - functions which were better documented in operating-system - manuals. And get_cycles() can fail or return a useless - 32-bit number. It might be available on some platforms, - such as arm, which we didn't test. Using - "include <linux/timex.h>" or "include <asm/timex.h>" - can lead to autoconf or compile errors, depending on system. - - rdtsc, __rdtsc, rdtscll: available for x86 with Linux BSD, - Solaris, Windows. See "possible flaws and dangers" comments. - - times(): what we use for ticks. Should just read the last - (xtime) tick count, therefore should be fast, but usually - isn't. - - GetTickCount(): we use this for my_timer_ticks() on - Windows. Actually it really is a tick counter, so resolution - >= 10 milliseconds unless you have a very old Windows version. - With Windows 95 or 98 or ME, timeGetTime() has better resolution than - GetTickCount (1ms rather than 55ms). But with Windows NT or XP or 2000, - they're both getting from a variable in the Process Environment Block - (PEB), and the variable is set by the programmable interrupt timer, so - the resolution is the same (usually 10-15 milliseconds). Also timeGetTime - is slower on old machines: - http://www.doumo.jp/aon-java/jsp/postgretips/tips.jsp?tips=74. - Also timeGetTime requires linking winmm.lib, - Therefore we use GetTickCount. - It will overflow every 49 days because the return is 32-bit. - There is also a GetTickCount64 but it requires Vista or Windows Server 2008. - (As for GetSystemTimeAsFileTime, its precision is spurious, it - just reads the tick variable like the other functions do. - However, we don't expect it to overflow every 49 days, so we - will prefer it for my_timer_milliseconds().) - - QueryPerformanceCounter() we use this for my_timer_microseconds() - on Windows. 1-PIT-tick (often 1/3-microsecond). Usually reads - the PIT so it's slow. On some Windows variants, uses RDTSC. - - GetLocalTime() this is available on Windows but we don't use it. - - getclock(): documented for Alpha, but not found during tests. - - mach_absolute_time() and UpTime() are recommended for Apple. - Inititally they weren't tried, because asm_ppc seems to do the job. - But now we use mach_absolute_time for nanoseconds. - - Any clock-based timer can be affected by NPT (ntpd program), - which means: - - full-second correction can occur for leap second - - tiny corrections can occcur approimately every 11 minutes - (but I think they only affect the RTC which isn't the PIT). - - We define "precision" as "frequency" and "high precision" is - "frequency better than 1 microsecond". We define "resolution" - as a synonym for "granularity". We define "accuracy" as - "closeness to the truth" as established by some authoritative - clock, but we can't measure accuracy. - - Do not expect any of our timers to be monotonic; we - won't guarantee that they return constantly-increasing - unique numbers. - - We tested with AIX, Solaris (x86 + Sparc), Linux (x86 + - Itanium), Windows, 64-bit Windows, QNX, FreeBSD, HPUX, - Irix, Mac. We didn't test with SCO. - -*/ - diff --git a/dep/mysqllite/mysys/my_read.c b/dep/mysqllite/mysys/my_read.c deleted file mode 100644 index dbe9006a1d3..00000000000 --- a/dep/mysqllite/mysys/my_read.c +++ /dev/null @@ -1,97 +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" -#include <my_base.h> -#include <errno.h> - -/* - Read a chunk of bytes from a file with retry's if needed - - The parameters are: - File descriptor - Buffer to hold at least Count bytes - Bytes to read - Flags on what to do on error - - Return: - -1 on error - 0 if flag has bits MY_NABP or MY_FNABP set - N number of bytes read. -*/ - -size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags) -{ - size_t readbytes, save_count; - DBUG_ENTER("my_read"); - DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", - Filedes, Buffer, (ulong) Count, MyFlags)); - save_count= Count; - - for (;;) - { - errno= 0; /* Linux, Windows don't reset this on EOF/success */ -#ifdef _WIN32 - readbytes= my_win_read(Filedes, Buffer, Count); -#else - readbytes= read(Filedes, Buffer, Count); -#endif - - if (readbytes != Count) - { - my_errno= errno; - if (errno == 0 || (readbytes != (size_t) -1 && - (MyFlags & (MY_NABP | MY_FNABP)))) - my_errno= HA_ERR_FILE_TOO_SHORT; - DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d", - (int) readbytes, (ulong) Count, Filedes, - my_errno)); - - if ((readbytes == 0 || (int) readbytes == -1) && errno == EINTR) - { - DBUG_PRINT("debug", ("my_read() was interrupted and returned %ld", - (long) readbytes)); - continue; /* Interrupted */ - } - - if (MyFlags & (MY_WME | MY_FAE | MY_FNABP)) - { - if (readbytes == (size_t) -1) - my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); - else if (MyFlags & (MY_NABP | MY_FNABP)) - my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG), - my_filename(Filedes),my_errno); - } - if (readbytes == (size_t) -1 || - ((MyFlags & (MY_FNABP | MY_NABP)) && !(MyFlags & MY_FULL_IO))) - DBUG_RETURN(MY_FILE_ERROR); /* Return with error */ - if (readbytes != (size_t) -1 && (MyFlags & MY_FULL_IO)) - { - Buffer+= readbytes; - Count-= readbytes; - continue; - } - } - - if (MyFlags & (MY_NABP | MY_FNABP)) - readbytes= 0; /* Ok on read */ - else if (MyFlags & MY_FULL_IO) - readbytes= save_count; - break; - } - DBUG_RETURN(readbytes); -} /* my_read */ diff --git a/dep/mysqllite/mysys/my_redel.c b/dep/mysqllite/mysys/my_redel.c deleted file mode 100644 index 92aa6e42073..00000000000 --- a/dep/mysqllite/mysys/my_redel.c +++ /dev/null @@ -1,124 +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 <my_dir.h> -#include <m_string.h> -#include "mysys_err.h" -#if defined(HAVE_UTIME_H) -#include <utime.h> -#elif defined(HAVE_SYS_UTIME_H) -#include <sys/utime.h> -#elif !defined(HPUX10) -struct utimbuf { - time_t actime; - time_t modtime; -}; -#endif - - /* - Rename with copy stat form old file - Copy stats from old file to new file, deletes orginal and - changes new file name to old file name - - if MY_REDEL_MAKE_COPY is given, then the orginal file - is renamed to org_name-'current_time'.BAK - */ - -#define REDEL_EXT ".BAK" - -int my_redel(const char *org_name, const char *tmp_name, myf MyFlags) -{ - int error=1; - DBUG_ENTER("my_redel"); - DBUG_PRINT("my",("org_name: '%s' tmp_name: '%s' MyFlags: %d", - org_name,tmp_name,MyFlags)); - - if (my_copystat(org_name,tmp_name,MyFlags) < 0) - goto end; - if (MyFlags & MY_REDEL_MAKE_BACKUP) - { - char name_buff[FN_REFLEN+20]; - char ext[20]; - ext[0]='-'; - get_date(ext+1,2+4,(time_t) 0); - strmov(strend(ext),REDEL_EXT); - if (my_rename(org_name, fn_format(name_buff, org_name, "", ext, 2), - MyFlags)) - goto end; - } - else if (my_delete_allow_opened(org_name, MyFlags)) - goto end; - if (my_rename(tmp_name,org_name,MyFlags)) - goto end; - - error=0; -end: - DBUG_RETURN(error); -} /* my_redel */ - - - /* Copy stat from one file to another */ - /* Return -1 if can't get stat, 1 if wrong type of file */ - -int my_copystat(const char *from, const char *to, int MyFlags) -{ - struct stat statbuf; - - if (stat(from, &statbuf)) - { - my_errno=errno; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_STAT, MYF(ME_BELL+ME_WAITTANG),from,errno); - return -1; /* Can't get stat on input file */ - } - if ((statbuf.st_mode & S_IFMT) != S_IFREG) - return 1; - - /* Copy modes */ - if (chmod(to, statbuf.st_mode & 07777)) - { - my_errno= errno; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_CHANGE_PERMISSIONS, MYF(ME_BELL+ME_WAITTANG), from, errno); - return -1; - } - -#if !defined(__WIN__) - 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); - } - /* Copy ownership */ - if (chown(to, statbuf.st_uid, statbuf.st_gid)) - { - my_errno= errno; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_CHANGE_OWNERSHIP, MYF(ME_BELL+ME_WAITTANG), from, errno); - return -1; - } -#endif /* !__WIN__ */ - - if (MyFlags & MY_COPYTIME) - { - struct utimbuf timep; - timep.actime = statbuf.st_atime; - timep.modtime = statbuf.st_mtime; - (void) utime((char*) to, &timep);/* Update last accessed and modified times */ - } - - return 0; -} /* my_copystat */ diff --git a/dep/mysqllite/mysys/my_rename.c b/dep/mysqllite/mysys/my_rename.c deleted file mode 100644 index 1a4e7b2b409..00000000000 --- a/dep/mysqllite/mysys/my_rename.c +++ /dev/null @@ -1,79 +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 <my_dir.h> -#include "mysys_err.h" -#include "m_string.h" -#undef my_rename - - /* On unix rename deletes to file if it exists */ - -int my_rename(const char *from, const char *to, myf MyFlags) -{ - int error = 0; - DBUG_ENTER("my_rename"); - DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); - -#if defined(HAVE_FILE_VERSIONS) - { /* Check that there isn't a old file */ - int save_errno; - MY_STAT my_stat_result; - save_errno=my_errno; - if (my_stat(to,&my_stat_result,MYF(0))) - { - my_errno=EEXIST; - error= -1; - if (MyFlags & MY_FAE+MY_WME) - my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG),from,to,my_errno); - DBUG_RETURN(error); - } - my_errno=save_errno; - } -#endif -#if defined(HAVE_RENAME) -#if defined(__WIN__) - /* - On windows we can't rename over an existing file: - Remove any conflicting files: - */ - (void) my_delete(to, MYF(0)); -#endif - if (rename(from,to)) -#else - if (link(from, to) || unlink(from)) -#endif - { - my_errno=errno; - error = -1; - if (MyFlags & (MY_FAE+MY_WME)) - my_error(EE_LINK, MYF(ME_BELL+ME_WAITTANG),from,to,my_errno); - } - else if (MyFlags & MY_SYNC_DIR) - { -#ifdef NEED_EXPLICIT_SYNC_DIR - /* do only the needed amount of syncs: */ - char dir_from[FN_REFLEN], dir_to[FN_REFLEN]; - size_t dir_from_length, dir_to_length; - dirname_part(dir_from, from, &dir_from_length); - dirname_part(dir_to, to, &dir_to_length); - if (my_sync_dir(dir_from, MyFlags) || - (strcmp(dir_from, dir_to) && - my_sync_dir(dir_to, MyFlags))) - error= -1; -#endif - } - DBUG_RETURN(error); -} /* my_rename */ diff --git a/dep/mysqllite/mysys/my_seek.c b/dep/mysqllite/mysys/my_seek.c deleted file mode 100644 index ca12a2e95d1..00000000000 --- a/dep/mysqllite/mysys/my_seek.c +++ /dev/null @@ -1,102 +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" - -/* - Seek to a position in a file. - - ARGUMENTS - File fd The file descriptor - my_off_t pos The expected position (absolute or relative) - int whence A direction parameter and one of - {SEEK_SET, SEEK_CUR, SEEK_END} - myf MyFlags MY_THREADSAFE must be set in case my_seek may be mixed - with my_pread/my_pwrite calls and fd is shared among - threads. - - DESCRIPTION - The my_seek function is a wrapper around the system call lseek and - repositions the offset of the file descriptor fd to the argument - offset according to the directive whence as follows: - SEEK_SET The offset is set to offset bytes. - SEEK_CUR The offset is set to its current location plus offset bytes - SEEK_END The offset is set to the size of the file plus offset bytes - - RETURN VALUE - my_off_t newpos The new position in the file. - MY_FILEPOS_ERROR An error was encountered while performing - the seek. my_errno is set to indicate the - actual error. -*/ - -my_off_t my_seek(File fd, my_off_t pos, int whence, myf MyFlags) -{ - os_off_t newpos= -1; - DBUG_ENTER("my_seek"); - DBUG_PRINT("my",("fd: %d Pos: %llu Whence: %d MyFlags: %d", - fd, (ulonglong) pos, whence, MyFlags)); - DBUG_ASSERT(pos != MY_FILEPOS_ERROR); /* safety check */ - - /* - Make sure we are using a valid file descriptor! - */ - DBUG_ASSERT(fd != -1); -#if defined (_WIN32) - newpos= my_win_lseek(fd, pos, whence); -#else - newpos= lseek(fd, pos, whence); -#endif - if (newpos == (os_off_t) -1) - { - my_errno= errno; - if (MyFlags & MY_WME) - my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno); - DBUG_PRINT("error", ("lseek: %llu errno: %d", (ulonglong) newpos, errno)); - DBUG_RETURN(MY_FILEPOS_ERROR); - } - if ((my_off_t) newpos != pos) - { - DBUG_PRINT("exit",("pos: %llu", (ulonglong) newpos)); - } - DBUG_RETURN((my_off_t) newpos); -} /* my_seek */ - - - /* Tell current position of file */ - /* ARGSUSED */ - -my_off_t my_tell(File fd, myf MyFlags) -{ - os_off_t pos; - DBUG_ENTER("my_tell"); - DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags)); - DBUG_ASSERT(fd >= 0); -#if defined (HAVE_TELL) && !defined (_WIN32) - pos= tell(fd); -#else - pos= my_seek(fd, 0L, MY_SEEK_CUR,0); -#endif - if (pos == (os_off_t) -1) - { - my_errno= errno; - if (MyFlags & MY_WME) - my_error(EE_CANT_SEEK, MYF(0), my_filename(fd), my_errno); - DBUG_PRINT("error", ("tell: %llu errno: %d", (ulonglong) pos, my_errno)); - } - DBUG_PRINT("exit",("pos: %llu", (ulonglong) pos)); - DBUG_RETURN((my_off_t) pos); -} /* my_tell */ diff --git a/dep/mysqllite/mysys/my_sleep.c b/dep/mysqllite/mysys/my_sleep.c deleted file mode 100644 index 6d1bdd5dc55..00000000000 --- a/dep/mysqllite/mysys/my_sleep.c +++ /dev/null @@ -1,35 +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 */ - -/* Wait a given number of microseconds */ - -#include "mysys_priv.h" -#include <m_string.h> - -void my_sleep(ulong m_seconds) -{ -#if defined(__WIN__) - Sleep(m_seconds/1000+1); /* Sleep() has millisecond arg */ -#elif defined(HAVE_SELECT) - struct timeval t; - t.tv_sec= m_seconds / 1000000L; - t.tv_usec= m_seconds % 1000000L; - select(0,0,0,0,&t); /* sleep */ -#else - uint sec= (uint) (m_seconds / 1000000L); - ulong start= (ulong) time((time_t*) 0); - while ((ulong) time((time_t*) 0) < start+sec); -#endif -} diff --git a/dep/mysqllite/mysys/my_static.c b/dep/mysqllite/mysys/my_static.c deleted file mode 100644 index ec8d66ab0cf..00000000000 --- a/dep/mysqllite/mysys/my_static.c +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. - - 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 */ - -/* - Static variables for mysys library. All definied here for easy making of - a shared library -*/ - -#include "mysys_priv.h" -#include "my_static.h" -#include "my_alarm.h" - -my_bool timed_mutexes= 0; - - /* from my_init */ -char * home_dir=0; -const char *my_progname=0; -char curr_dir[FN_REFLEN]= {0}, - home_dir_buff[FN_REFLEN]= {0}; -ulong my_stream_opened=0,my_file_opened=0, my_tmp_file_created=0; -ulong my_file_total_opened= 0; -int my_umask=0664, my_umask_dir=0777; - -struct st_my_file_info my_file_info_default[MY_NFILE]; -uint my_file_limit= MY_NFILE; -struct st_my_file_info *my_file_info= my_file_info_default; - - /* From mf_brkhant */ -int my_dont_interrupt=0; -volatile int _my_signals=0; -struct st_remember _my_sig_remember[MAX_SIGNALS]={{0,0}}; - - /* from mf_reccache.c */ -ulong my_default_record_cache_size=RECORD_CACHE_SIZE; - - /* from soundex.c */ - /* ABCDEFGHIJKLMNOPQRSTUVWXYZ */ - /* :::::::::::::::::::::::::: */ -const char *soundex_map= "01230120022455012623010202"; - - /* from my_malloc */ -USED_MEM* my_once_root_block=0; /* pointer to first block */ -uint my_once_extra=ONCE_ALLOC_INIT; /* Memory to alloc / block */ - - /* from my_largepage.c */ -#ifdef HAVE_LARGE_PAGES -my_bool my_use_large_pages= 0; -uint my_large_page_size= 0; -#endif - - /* from my_alarm */ -int volatile my_have_got_alarm=0; /* declare variable to reset */ -ulong my_time_to_wait_for_lock=2; /* In seconds */ - - /* from errors.c */ -#ifdef SHARED_LIBRARY -const char *globerrs[GLOBERRS]; /* my_error_messages is here */ -#endif -void (*my_abort_hook)(int) = (void(*)(int)) exit; -void (*error_handler_hook)(uint error, const char *str, myf MyFlags)= - my_message_stderr; -void (*fatal_error_handler_hook)(uint error, const char *str, myf MyFlags)= - my_message_stderr; - -static const char *proc_info_dummy(void *a __attribute__((unused)), - const char *b __attribute__((unused)), - const char *c __attribute__((unused)), - const char *d __attribute__((unused)), - const unsigned int e __attribute__((unused))) -{ - return 0; -} - -/* this is to be able to call set_thd_proc_info from the C code */ -const char *(*proc_info_hook)(void *, const char *, const char *, const char *, - const unsigned int)= proc_info_dummy; - -#if defined(ENABLED_DEBUG_SYNC) -/** - Global pointer to be set if callback function is defined - (e.g. in mysqld). See sql/debug_sync.cc. -*/ -void (*debug_sync_C_callback_ptr)(const char *, size_t); -#endif /* defined(ENABLED_DEBUG_SYNC) */ - -#ifdef __WIN__ -/* from my_getsystime.c */ -ulonglong query_performance_frequency, query_performance_offset; -#endif - - /* How to disable options */ -my_bool my_disable_locking=0; -my_bool my_disable_async_io=0; -my_bool my_disable_flush_key_blocks=0; -my_bool my_disable_symlinks=0; - -/* - Note that PSI_hook and PSI_server are unconditionally - (no ifdef HAVE_PSI_INTERFACE) defined. - This is to ensure binary compatibility between the server and plugins, - in the case when: - - the server is not compiled with HAVE_PSI_INTERFACE - - a plugin is compiled with HAVE_PSI_INTERFACE - See the doxygen documentation for the performance schema. -*/ - -/** - Hook for the instrumentation interface. - Code implementing the instrumentation interface should register here. -*/ -struct PSI_bootstrap *PSI_hook= NULL; - -/** - Instance of the instrumentation interface for the MySQL server. - @todo This is currently a global variable, which is handy when - compiling instrumented code that is bundled with the server. - When dynamic plugin are truly supported, this variable will need - to be replaced by a macro, so that each XYZ plugin can have it's own - xyz_psi_server variable, obtained from PSI_bootstrap::get_interface() - with the version used at compile time for plugin XYZ. -*/ -PSI *PSI_server= NULL; - diff --git a/dep/mysqllite/mysys/my_static.h b/dep/mysqllite/mysys/my_static.h deleted file mode 100644 index 7fde15ff133..00000000000 --- a/dep/mysqllite/mysys/my_static.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef MYSYS_MY_STATIC_INCLUDED -#define MYSYS_MY_STATIC_INCLUDED - -/* 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 */ - -/* - Static variables for mysys library. All definied here for easy making of - a shared library -*/ - -C_MODE_START -#include <signal.h> - -#define MAX_SIGNALS 10 /* Max signals under a dont-allow */ - -struct st_remember { - int number; - sig_handler (*func)(int number); -}; - -extern char curr_dir[FN_REFLEN], home_dir_buff[FN_REFLEN]; - -extern volatile int _my_signals; -extern struct st_remember _my_sig_remember[MAX_SIGNALS]; - -extern const char *soundex_map; - -extern USED_MEM* my_once_root_block; -extern uint my_once_extra; - -extern struct st_my_file_info my_file_info_default[MY_NFILE]; - -extern ulonglong query_performance_frequency, query_performance_offset; - -C_MODE_END - -#endif /* MYSYS_MY_STATIC_INCLUDED */ diff --git a/dep/mysqllite/mysys/my_symlink.c b/dep/mysqllite/mysys/my_symlink.c deleted file mode 100644 index 053fc887fe8..00000000000 --- a/dep/mysqllite/mysys/my_symlink.c +++ /dev/null @@ -1,167 +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" -#include <m_string.h> -#include <errno.h> -#ifdef HAVE_REALPATH -#include <sys/param.h> -#include <sys/stat.h> -#endif - -/* - Reads the content of a symbolic link - If the file is not a symbolic link, return the original file name in to. - - RETURN - 0 If filename was a symlink, (to will be set to value of symlink) - 1 If filename was a normal file (to will be set to filename) - -1 on error. -*/ - -int my_readlink(char *to, const char *filename, myf MyFlags) -{ -#ifndef HAVE_READLINK - strmov(to,filename); - return 1; -#else - int result=0; - int length; - DBUG_ENTER("my_readlink"); - - if ((length=readlink(filename, to, FN_REFLEN-1)) < 0) - { - /* Don't give an error if this wasn't a symlink */ - if ((my_errno=errno) == EINVAL) - { - result= 1; - strmov(to,filename); - } - else - { - if (MyFlags & MY_WME) - my_error(EE_CANT_READLINK, MYF(0), filename, errno); - result= -1; - } - } - else - to[length]=0; - DBUG_PRINT("exit" ,("result: %d", result)); - DBUG_RETURN(result); -#endif /* HAVE_READLINK */ -} - - -/* Create a symbolic link */ - -int my_symlink(const char *content, const char *linkname, myf MyFlags) -{ -#ifndef HAVE_READLINK - return 0; -#else - int result; - DBUG_ENTER("my_symlink"); - DBUG_PRINT("enter",("content: %s linkname: %s", content, linkname)); - - result= 0; - if (symlink(content, linkname)) - { - result= -1; - my_errno=errno; - if (MyFlags & MY_WME) - my_error(EE_CANT_SYMLINK, MYF(0), linkname, content, errno); - } - else if ((MyFlags & MY_SYNC_DIR) && my_sync_dir_by_file(linkname, MyFlags)) - result= -1; - DBUG_RETURN(result); -#endif /* HAVE_READLINK */ -} - -#if defined(SCO) -#define BUFF_LEN 4097 -#elif defined(MAXPATHLEN) -#define BUFF_LEN MAXPATHLEN -#else -#define BUFF_LEN FN_LEN -#endif - - -int my_is_symlink(const char *filename __attribute__((unused))) -{ -#if defined (HAVE_LSTAT) && defined (S_ISLNK) - struct stat stat_buff; - return !lstat(filename, &stat_buff) && S_ISLNK(stat_buff.st_mode); -#elif defined (_WIN32) - DWORD dwAttr = GetFileAttributes(filename); - return (dwAttr != INVALID_FILE_ATTRIBUTES) && - (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT); -#else /* No symlinks */ - return 0; -#endif -} - -/* - Resolve all symbolic links in path - 'to' may be equal to 'filename' -*/ - -int my_realpath(char *to, const char *filename, myf MyFlags) -{ -#if defined(HAVE_REALPATH) && !defined(HAVE_BROKEN_REALPATH) - int result=0; - char buff[BUFF_LEN]; - char *ptr; - DBUG_ENTER("my_realpath"); - - DBUG_PRINT("info",("executing realpath")); - if ((ptr=realpath(filename,buff))) - strmake(to,ptr,FN_REFLEN-1); - else - { - /* - Realpath didn't work; Use my_load_path() which is a poor substitute - original name but will at least be able to resolve paths that starts - with '.'. - */ - DBUG_PRINT("error",("realpath failed with errno: %d", errno)); - my_errno=errno; - if (MyFlags & MY_WME) - my_error(EE_REALPATH, MYF(0), filename, my_errno); - my_load_path(to, filename, NullS); - result= -1; - } - DBUG_RETURN(result); -#else -#ifdef _WIN32 - int ret= GetFullPathName(filename,FN_REFLEN, - to, - NULL); - if (ret == 0 || ret > FN_REFLEN) - { - if (ret > FN_REFLEN) - my_errno= ENAMETOOLONG; - else - my_errno= EACCES; - if (MyFlags & MY_WME) - my_error(EE_REALPATH, MYF(0), filename, my_errno); - return -1; - } -#else - my_load_path(to, filename, NullS); -#endif - return 0; -#endif -} diff --git a/dep/mysqllite/mysys/my_symlink2.c b/dep/mysqllite/mysys/my_symlink2.c deleted file mode 100644 index 7c3ddbb911c..00000000000 --- a/dep/mysqllite/mysys/my_symlink2.c +++ /dev/null @@ -1,183 +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 */ - -/* - Advanced symlink handling. - This is used in MyISAM to let users symlinks tables to different disk. - The main idea with these functions is to automaticly create, delete and - rename files and symlinks like they would be one unit. -*/ - -#include "mysys_priv.h" -#include "mysys_err.h" -#include <m_string.h> - -File my_create_with_symlink(const char *linkname, const char *filename, - int createflags, int access_flags, myf MyFlags) -{ - File file; - int tmp_errno; - /* Test if we should create a link */ - int create_link; - char abs_linkname[FN_REFLEN]; - DBUG_ENTER("my_create_with_symlink"); - DBUG_PRINT("enter", ("linkname: %s filename: %s", - linkname ? linkname : "(null)", - filename ? filename : "(null)")); - - if (my_disable_symlinks) - { - DBUG_PRINT("info", ("Symlinks disabled")); - /* Create only the file, not the link and file */ - create_link= 0; - if (linkname) - filename= linkname; - } - else - { - if (linkname) - my_realpath(abs_linkname, linkname, MYF(0)); - create_link= (linkname && strcmp(abs_linkname,filename)); - } - - if (!(MyFlags & MY_DELETE_OLD)) - { - if (!access(filename,F_OK)) - { - my_errno= errno= EEXIST; - my_error(EE_CANTCREATEFILE, MYF(0), filename, EEXIST); - DBUG_RETURN(-1); - } - if (create_link && !access(linkname,F_OK)) - { - my_errno= errno= EEXIST; - my_error(EE_CANTCREATEFILE, MYF(0), linkname, EEXIST); - DBUG_RETURN(-1); - } - } - - if ((file=my_create(filename, createflags, access_flags, MyFlags)) >= 0) - { - if (create_link) - { - /* Delete old link/file */ - if (MyFlags & MY_DELETE_OLD) - my_delete(linkname, MYF(0)); - /* Create link */ - if (my_symlink(filename, linkname, MyFlags)) - { - /* Fail, remove everything we have done */ - tmp_errno=my_errno; - my_close(file,MYF(0)); - my_delete(filename, MYF(0)); - file= -1; - my_errno=tmp_errno; - } - } - } - DBUG_RETURN(file); -} - -/* - If the file was a symlink, delete both symlink and the file which the - symlink pointed to. -*/ - -int my_delete_with_symlink(const char *name, myf MyFlags) -{ - char link_name[FN_REFLEN]; - int was_symlink= (!my_disable_symlinks && - !my_readlink(link_name, name, MYF(0))); - int result; - DBUG_ENTER("my_delete_with_symlink"); - - if (!(result=my_delete(name, MyFlags))) - { - if (was_symlink) - result=my_delete(link_name, MyFlags); - } - DBUG_RETURN(result); -} - -/* - If the file is a normal file, just rename it. - If the file is a symlink: - - Create a new file with the name 'to' that points at - symlink_dir/basename(to) - - Rename the symlinked file to symlink_dir/basename(to) - - Delete 'from' - If something goes wrong, restore everything. -*/ - -int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) -{ -#ifndef HAVE_READLINK - return my_rename(from, to, MyFlags); -#else - char link_name[FN_REFLEN], tmp_name[FN_REFLEN]; - int was_symlink= (!my_disable_symlinks && - !my_readlink(link_name, from, MYF(0))); - int result=0; - int name_is_different; - DBUG_ENTER("my_rename_with_symlink"); - - if (!was_symlink) - DBUG_RETURN(my_rename(from, to, MyFlags)); - - /* Change filename that symlink pointed to */ - strmov(tmp_name, to); - fn_same(tmp_name,link_name,1); /* Copy dir */ - name_is_different= strcmp(link_name, tmp_name); - if (name_is_different && !access(tmp_name, F_OK)) - { - my_errno= EEXIST; - if (MyFlags & MY_WME) - my_error(EE_CANTCREATEFILE, MYF(0), tmp_name, EEXIST); - DBUG_RETURN(1); - } - - /* Create new symlink */ - if (my_symlink(tmp_name, to, MyFlags)) - DBUG_RETURN(1); - - /* - Rename symlinked file if the base name didn't change. - This can happen if you use this function where 'from' and 'to' has - the same basename and different directories. - */ - - if (name_is_different && my_rename(link_name, tmp_name, MyFlags)) - { - int save_errno=my_errno; - my_delete(to, MyFlags); /* Remove created symlink */ - my_errno=save_errno; - DBUG_RETURN(1); - } - - /* Remove original symlink */ - if (my_delete(from, MyFlags)) - { - int save_errno=my_errno; - /* Remove created link */ - my_delete(to, MyFlags); - /* Rename file back */ - if (strcmp(link_name, tmp_name)) - (void) my_rename(tmp_name, link_name, MyFlags); - my_errno=save_errno; - result= 1; - } - DBUG_RETURN(result); -#endif /* HAVE_READLINK */ -} diff --git a/dep/mysqllite/mysys/my_sync.c b/dep/mysqllite/mysys/my_sync.c deleted file mode 100644 index e33a9342afa..00000000000 --- a/dep/mysqllite/mysys/my_sync.c +++ /dev/null @@ -1,175 +0,0 @@ -/* Copyright (C) 2003 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" -#include <errno.h> - -/* - Sync data in file to disk - - SYNOPSIS - my_sync() - fd File descritor to sync - my_flags Flags (now only MY_WME is supported) - - NOTE - If file system supports its, only file data is synced, not inode data. - - MY_IGNORE_BADFD is useful when fd is "volatile" - not protected by a - mutex. In this case by the time of fsync(), fd may be already closed by - another thread, or even reassigned to a different file. With this flag - - MY_IGNORE_BADFD - such a situation will not be considered an error. - (which is correct behaviour, if we know that the other thread synced the - file before closing) - - RETURN - 0 ok - -1 error -*/ - -int my_sync(File fd, myf my_flags) -{ - int res; - DBUG_ENTER("my_sync"); - DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags)); - - do - { -#if defined(F_FULLFSYNC) - /* - In Mac OS X >= 10.3 this call is safer than fsync() (it forces the - disk's cache and guarantees ordered writes). - */ - if (!(res= fcntl(fd, F_FULLFSYNC, 0))) - break; /* ok */ - /* Some file systems don't support F_FULLFSYNC and fail above: */ - DBUG_PRINT("info",("fcntl(F_FULLFSYNC) failed, falling back")); -#endif -#if defined(HAVE_FDATASYNC) && HAVE_DECL_FDATASYNC - res= fdatasync(fd); -#elif defined(HAVE_FSYNC) - res= fsync(fd); -#elif defined(_WIN32) - res= my_win_fsync(fd); -#else -#error Cannot find a way to sync a file, durability in danger - res= 0; /* No sync (strange OS) */ -#endif - } while (res == -1 && errno == EINTR); - - if (res) - { - int er= errno; - if (!(my_errno= er)) - my_errno= -1; /* Unknown error */ - if ((my_flags & MY_IGNORE_BADFD) && - (er == EBADF || er == EINVAL || er == EROFS)) - { - DBUG_PRINT("info", ("ignoring errno %d", er)); - res= 0; - } - else if (my_flags & MY_WME) - my_error(EE_SYNC, MYF(ME_BELL+ME_WAITTANG), my_filename(fd), my_errno); - } - DBUG_RETURN(res); -} /* my_sync */ - - -static const char cur_dir_name[]= {FN_CURLIB, 0}; - - -/* - Force directory information to disk. - - SYNOPSIS - my_sync_dir() - dir_name the name of the directory - my_flags flags (MY_WME etc) - - RETURN - 0 if ok, !=0 if error -*/ - -#ifdef NEED_EXPLICIT_SYNC_DIR - -int my_sync_dir(const char *dir_name, myf my_flags) -{ - File dir_fd; - int res= 0; - const char *correct_dir_name; - DBUG_ENTER("my_sync_dir"); - DBUG_PRINT("my",("Dir: '%s' my_flags: %d", dir_name, my_flags)); - /* Sometimes the path does not contain an explicit directory */ - correct_dir_name= (dir_name[0] == 0) ? cur_dir_name : dir_name; - /* - Syncing a dir may give EINVAL on tmpfs on Linux, which is ok. - EIO on the other hand is very important. Hence MY_IGNORE_BADFD. - */ - if ((dir_fd= my_open(correct_dir_name, O_RDONLY, MYF(my_flags))) >= 0) - { - if (my_sync(dir_fd, MYF(my_flags | MY_IGNORE_BADFD))) - res= 2; - if (my_close(dir_fd, MYF(my_flags))) - res= 3; - } - else - res= 1; - DBUG_RETURN(res); -} - -#else /* NEED_EXPLICIT_SYNC_DIR */ - -int my_sync_dir(const char *dir_name __attribute__((unused)), - myf my_flags __attribute__((unused))) -{ - return 0; -} - -#endif /* NEED_EXPLICIT_SYNC_DIR */ - - -/* - Force directory information to disk. - - SYNOPSIS - my_sync_dir_by_file() - file_name the name of a file in the directory - my_flags flags (MY_WME etc) - - RETURN - 0 if ok, !=0 if error -*/ - -#ifdef NEED_EXPLICIT_SYNC_DIR - -int my_sync_dir_by_file(const char *file_name, myf my_flags) -{ - char dir_name[FN_REFLEN]; - size_t dir_name_length; - dirname_part(dir_name, file_name, &dir_name_length); - return my_sync_dir(dir_name, my_flags); -} - -#else /* NEED_EXPLICIT_SYNC_DIR */ - -int my_sync_dir_by_file(const char *file_name __attribute__((unused)), - myf my_flags __attribute__((unused))) -{ - return 0; -} - -#endif /* NEED_EXPLICIT_SYNC_DIR */ - diff --git a/dep/mysqllite/mysys/my_thr_init.c b/dep/mysqllite/mysys/my_thr_init.c deleted file mode 100644 index c4b56cde850..00000000000 --- a/dep/mysqllite/mysys/my_thr_init.c +++ /dev/null @@ -1,533 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* - Functions to handle initializating and allocationg of all mysys & debug - thread variables. -*/ - -#include "mysys_priv.h" -#include <m_string.h> -#include <signal.h> - -pthread_key(struct st_my_thread_var*, THR_KEY_mysys); -mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, - THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_myisam, THR_LOCK_heap, - THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time, - THR_LOCK_myisam_mmap; - -mysql_cond_t THR_COND_threads; -uint THR_thread_count= 0; -uint my_thread_end_wait_time= 5; -#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) -mysql_mutex_t LOCK_localtime_r; -#endif -#ifndef HAVE_GETHOSTBYNAME_R -mysql_mutex_t LOCK_gethostbyname_r; -#endif -#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP -pthread_mutexattr_t my_fast_mutexattr; -#endif -#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP -pthread_mutexattr_t my_errorcheck_mutexattr; -#endif -#ifdef _MSC_VER -static void install_sigabrt_handler(); -#endif -#ifdef TARGET_OS_LINUX - -/* - Dummy thread spawned in my_thread_global_init() below to avoid - race conditions in NPTL pthread_exit code. -*/ - -static pthread_handler_t -nptl_pthread_exit_hack_handler(void *arg __attribute((unused))) -{ - /* Do nothing! */ - pthread_exit(0); - return 0; -} - -#endif /* TARGET_OS_LINUX */ - - -static uint get_thread_lib(void); - -/** True if @c my_thread_basic_global_init() has been called. */ -static my_bool my_thread_basic_global_init_done= 0; - -/** - Perform a minimal initialisation of mysys, when compiled with threads. - The initialisation performed is sufficient to: - - allocate memory - - perform file operations - - use charsets - - use my_errno - @sa my_basic_init - @sa my_thread_basic_global_reinit -*/ -my_bool my_thread_basic_global_init(void) -{ - int pth_ret; - - if (my_thread_basic_global_init_done) - return 0; - my_thread_basic_global_init_done= 1; - -#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP - /* - Set mutex type to "fast" a.k.a "adaptive" - - In this case the thread may steal the mutex from some other thread - that is waiting for the same mutex. This will save us some - context switches but may cause a thread to 'starve forever' while - waiting for the mutex (not likely if the code within the mutex is - short). - */ - pthread_mutexattr_init(&my_fast_mutexattr); - pthread_mutexattr_settype(&my_fast_mutexattr, - PTHREAD_MUTEX_ADAPTIVE_NP); -#endif - -#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP - /* - Set mutex type to "errorcheck" - */ - pthread_mutexattr_init(&my_errorcheck_mutexattr); - pthread_mutexattr_settype(&my_errorcheck_mutexattr, - PTHREAD_MUTEX_ERRORCHECK); -#endif - - mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); - - if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0) - { - fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret); - return 1; - } - - if (my_thread_init()) - return 1; - - return 0; -} - -/** - Re-initialize components initialized early with @c my_thread_basic_global_init. - Some mutexes were initialized before the instrumentation. - Destroy + create them again, now that the instrumentation - is in place. - This is safe, since this function() is called before creating new threads, - so the mutexes are not in use. -*/ -void my_thread_basic_global_reinit(void) -{ - struct st_my_thread_var *tmp; - - DBUG_ASSERT(my_thread_basic_global_init_done); - -#ifdef HAVE_PSI_INTERFACE - my_init_mysys_psi_keys(); -#endif - - mysql_mutex_destroy(&THR_LOCK_malloc); - mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); - - mysql_mutex_destroy(&THR_LOCK_open); - mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); - - mysql_mutex_destroy(&THR_LOCK_charset); - mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); - - mysql_mutex_destroy(&THR_LOCK_threads); - mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); - - tmp= my_pthread_getspecific(struct st_my_thread_var*, THR_KEY_mysys); - DBUG_ASSERT(tmp); - - mysql_mutex_destroy(&tmp->mutex); - mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); - - mysql_cond_destroy(&tmp->suspend); - mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL); -} - -/* - initialize thread environment - - SYNOPSIS - my_thread_global_init() - - RETURN - 0 ok - 1 error (Couldn't create THR_KEY_mysys) -*/ - -my_bool my_thread_global_init(void) -{ - if (my_thread_basic_global_init()) - return 1; - - thd_lib_detected= get_thread_lib(); - -#ifdef TARGET_OS_LINUX - /* - BUG#24507: Race conditions inside current NPTL pthread_exit() - implementation. - - To avoid a possible segmentation fault during concurrent - executions of pthread_exit(), a dummy thread is spawned which - initializes internal variables of pthread lib. See bug description - for a full explanation. - - TODO: Remove this code when fixed versions of glibc6 are in common - use. - */ - if (thd_lib_detected == THD_LIB_NPTL) - { - pthread_t dummy_thread; - pthread_attr_t dummy_thread_attr; - - pthread_attr_init(&dummy_thread_attr); - pthread_attr_setdetachstate(&dummy_thread_attr, PTHREAD_CREATE_JOINABLE); - - if (pthread_create(&dummy_thread,&dummy_thread_attr, - nptl_pthread_exit_hack_handler, NULL) == 0) - (void)pthread_join(dummy_thread, NULL); - } -#endif /* TARGET_OS_LINUX */ - - mysql_mutex_init(key_THR_LOCK_lock, &THR_LOCK_lock, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_THR_LOCK_isam, &THR_LOCK_isam, MY_MUTEX_INIT_SLOW); - mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW); - mysql_mutex_init(key_THR_LOCK_myisam_mmap, &THR_LOCK_myisam_mmap, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_THR_LOCK_heap, &THR_LOCK_heap, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_THR_LOCK_net, &THR_LOCK_net, MY_MUTEX_INIT_FAST); - mysql_mutex_init(key_THR_LOCK_time, &THR_LOCK_time, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_THR_COND_threads, &THR_COND_threads, NULL); - -#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) - mysql_mutex_init(key_LOCK_localtime_r, &LOCK_localtime_r, MY_MUTEX_INIT_SLOW); -#endif -#ifndef HAVE_GETHOSTBYNAME_R - mysql_mutex_init(key_LOCK_gethostbyname_r, - &LOCK_gethostbyname_r, MY_MUTEX_INIT_SLOW); -#endif - -#ifdef _MSC_VER - install_sigabrt_handler(); -#endif - - if (my_thread_init()) - { - my_thread_global_end(); /* Clean up */ - return 1; - } - return 0; -} - - -void my_thread_global_end(void) -{ - struct timespec abstime; - my_bool all_threads_killed= 1; - - set_timespec(abstime, my_thread_end_wait_time); - mysql_mutex_lock(&THR_LOCK_threads); - while (THR_thread_count > 0) - { - int error= mysql_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads, - &abstime); - if (error == ETIMEDOUT || error == ETIME) - { -#ifdef HAVE_PTHREAD_KILL - /* - We shouldn't give an error here, because if we don't have - pthread_kill(), programs like mysqld can't ensure that all threads - are killed when we enter here. - */ - if (THR_thread_count) - fprintf(stderr, - "Error in my_thread_global_end(): %d threads didn't exit\n", - THR_thread_count); -#endif - all_threads_killed= 0; - break; - } - } - mysql_mutex_unlock(&THR_LOCK_threads); - - pthread_key_delete(THR_KEY_mysys); -#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP - pthread_mutexattr_destroy(&my_fast_mutexattr); -#endif -#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP - pthread_mutexattr_destroy(&my_errorcheck_mutexattr); -#endif - mysql_mutex_destroy(&THR_LOCK_malloc); - mysql_mutex_destroy(&THR_LOCK_open); - mysql_mutex_destroy(&THR_LOCK_lock); - mysql_mutex_destroy(&THR_LOCK_isam); - mysql_mutex_destroy(&THR_LOCK_myisam); - mysql_mutex_destroy(&THR_LOCK_myisam_mmap); - mysql_mutex_destroy(&THR_LOCK_heap); - mysql_mutex_destroy(&THR_LOCK_net); - mysql_mutex_destroy(&THR_LOCK_time); - mysql_mutex_destroy(&THR_LOCK_charset); - if (all_threads_killed) - { - mysql_mutex_destroy(&THR_LOCK_threads); - mysql_cond_destroy(&THR_COND_threads); - } -#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) - mysql_mutex_destroy(&LOCK_localtime_r); -#endif -#ifndef HAVE_GETHOSTBYNAME_R - mysql_mutex_destroy(&LOCK_gethostbyname_r); -#endif - - my_thread_basic_global_init_done= 0; -} - -static my_thread_id thread_id= 0; - -/* - Allocate thread specific memory for the thread, used by mysys and dbug - - SYNOPSIS - my_thread_init() - - NOTES - We can't use mutex_locks here if we are using windows as - we may have compiled the program with SAFE_MUTEX, in which - case the checking of mutex_locks will not work until - the pthread_self thread specific variable is initialized. - - This function may called multiple times for a thread, for example - if one uses my_init() followed by mysql_server_init(). - - RETURN - 0 ok - 1 Fatal error; mysys/dbug functions can't be used -*/ - -my_bool my_thread_init(void) -{ - struct st_my_thread_var *tmp; - my_bool error=0; - -#ifdef EXTRA_DEBUG_THREADS - fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n", - (ulong) pthread_self()); -#endif - - if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) - { -#ifdef EXTRA_DEBUG_THREADS - fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n", - (long) pthread_self()); -#endif - goto end; - } - -#ifdef _MSC_VER - install_sigabrt_handler(); -#endif - - if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp)))) - { - error= 1; - goto end; - } - pthread_setspecific(THR_KEY_mysys,tmp); - tmp->pthread_self= pthread_self(); - mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL); - - tmp->stack_ends_here= (char*)&tmp + - STACK_DIRECTION * (long)my_thread_stack_size; - - mysql_mutex_lock(&THR_LOCK_threads); - tmp->id= ++thread_id; - ++THR_thread_count; - mysql_mutex_unlock(&THR_LOCK_threads); - tmp->init= 1; -#ifndef DBUG_OFF - /* Generate unique name for thread */ - (void) my_thread_name(); -#endif - -end: - return error; -} - - -/* - Deallocate memory used by the thread for book-keeping - - SYNOPSIS - my_thread_end() - - NOTE - This may be called multiple times for a thread. - This happens for example when one calls 'mysql_server_init()' - mysql_server_end() and then ends with a mysql_end(). -*/ - -void my_thread_end(void) -{ - struct st_my_thread_var *tmp; - tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); - -#ifdef EXTRA_DEBUG_THREADS - fprintf(stderr,"my_thread_end(): tmp: 0x%lx pthread_self: 0x%lx thread_id: %ld\n", - (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L); -#endif - -#ifdef HAVE_PSI_INTERFACE - /* - Remove the instrumentation for this thread. - This must be done before trashing st_my_thread_var, - because the LF_HASH depends on it. - */ - if (PSI_server) - PSI_server->delete_current_thread(); -#endif - - if (tmp && tmp->init) - { -#if !defined(DBUG_OFF) - /* tmp->dbug is allocated inside DBUG library */ - if (tmp->dbug) - { - DBUG_POP(); - free(tmp->dbug); - tmp->dbug=0; - } -#endif -#if !defined(__bsdi__) && !defined(__OpenBSD__) - /* bsdi and openbsd 3.5 dumps core here */ - mysql_cond_destroy(&tmp->suspend); -#endif - mysql_mutex_destroy(&tmp->mutex); - free(tmp); - - /* - Decrement counter for number of running threads. We are using this - in my_thread_global_end() to wait until all threads have called - my_thread_end and thus freed all memory they have allocated in - my_thread_init() and DBUG_xxxx - */ - mysql_mutex_lock(&THR_LOCK_threads); - DBUG_ASSERT(THR_thread_count != 0); - if (--THR_thread_count == 0) - mysql_cond_signal(&THR_COND_threads); - mysql_mutex_unlock(&THR_LOCK_threads); - } - pthread_setspecific(THR_KEY_mysys,0); -} - -struct st_my_thread_var *_my_thread_var(void) -{ - return my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); -} - - -/**************************************************************************** - Get name of current thread. -****************************************************************************/ - -my_thread_id my_thread_dbug_id() -{ - return my_thread_var->id; -} - -#ifdef DBUG_OFF -const char *my_thread_name(void) -{ - return "no_name"; -} - -#else - -const char *my_thread_name(void) -{ - char name_buff[100]; - struct st_my_thread_var *tmp=my_thread_var; - if (!tmp->name[0]) - { - my_thread_id id= my_thread_dbug_id(); - sprintf(name_buff,"T@%lu", (ulong) id); - strmake(tmp->name,name_buff,THREAD_NAME_SIZE); - } - return tmp->name; -} - -/* Return pointer to DBUG for holding current state */ - -extern void **my_thread_var_dbug() -{ - struct st_my_thread_var *tmp= - my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); - return tmp && tmp->init ? &tmp->dbug : 0; -} -#endif /* DBUG_OFF */ - - -static uint get_thread_lib(void) -{ -#ifdef _CS_GNU_LIBPTHREAD_VERSION - char buff[64]; - - confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff)); - - if (!strncasecmp(buff, "NPTL", 4)) - return THD_LIB_NPTL; - if (!strncasecmp(buff, "linuxthreads", 12)) - return THD_LIB_LT; -#endif - return THD_LIB_OTHER; -} - -#ifdef _WIN32 -/* - In Visual Studio 2005 and later, default SIGABRT handler will overwrite - any unhandled exception filter set by the application and will try to - call JIT debugger. This is not what we want, this we calling __debugbreak - to stop in debugger, if process is being debugged or to generate - EXCEPTION_BREAKPOINT and then handle_segfault will do its magic. -*/ - -#if (_MSC_VER >= 1400) -static void my_sigabrt_handler(int sig) -{ - __debugbreak(); -} -#endif /*_MSC_VER >=1400 */ - -static void install_sigabrt_handler(void) -{ -#if (_MSC_VER >=1400) - /*abort() should not override our exception filter*/ - _set_abort_behavior(0,_CALL_REPORTFAULT); - signal(SIGABRT,my_sigabrt_handler); -#endif /* _MSC_VER >=1400 */ -} -#endif - diff --git a/dep/mysqllite/mysys/my_wincond.c b/dep/mysqllite/mysys/my_wincond.c deleted file mode 100644 index 58c09e332d6..00000000000 --- a/dep/mysqllite/mysys/my_wincond.c +++ /dev/null @@ -1,369 +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 */ - -/***************************************************************************** -** The following is a simple implementation of posix conditions -*****************************************************************************/ -#if defined(_WIN32) - -#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */ -#include "mysys_priv.h" -#include <m_string.h> -#include <process.h> -#include <sys/timeb.h> - - -/* - Windows native condition variables. We use runtime loading / function - pointers, because they are not available on XP -*/ - -/* Prototypes and function pointers for condition variable functions */ -typedef VOID (WINAPI * InitializeConditionVariableProc) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI * SleepConditionVariableCSProc) - (PCONDITION_VARIABLE ConditionVariable, - PCRITICAL_SECTION CriticalSection, - DWORD dwMilliseconds); - -typedef VOID (WINAPI * WakeAllConditionVariableProc) - (PCONDITION_VARIABLE ConditionVariable); - -typedef VOID (WINAPI * WakeConditionVariableProc) - (PCONDITION_VARIABLE ConditionVariable); - -static InitializeConditionVariableProc my_InitializeConditionVariable; -static SleepConditionVariableCSProc my_SleepConditionVariableCS; -static WakeAllConditionVariableProc my_WakeAllConditionVariable; -static WakeConditionVariableProc my_WakeConditionVariable; - - -/** - Indicates if we have native condition variables, - initialized first time pthread_cond_init is called. -*/ - -static BOOL have_native_conditions= FALSE; - - -/** - Check if native conditions can be used, load function pointers -*/ - -static void check_native_cond_availability(void) -{ - HMODULE module= GetModuleHandle("kernel32"); - - my_InitializeConditionVariable= (InitializeConditionVariableProc) - GetProcAddress(module, "InitializeConditionVariable"); - my_SleepConditionVariableCS= (SleepConditionVariableCSProc) - GetProcAddress(module, "SleepConditionVariableCS"); - my_WakeAllConditionVariable= (WakeAllConditionVariableProc) - GetProcAddress(module, "WakeAllConditionVariable"); - my_WakeConditionVariable= (WakeConditionVariableProc) - GetProcAddress(module, "WakeConditionVariable"); - - if (my_InitializeConditionVariable) - have_native_conditions= TRUE; -} - - - -/** - Convert abstime to milliseconds -*/ - -static DWORD get_milliseconds(const struct timespec *abstime) -{ - long long millis; - union ft64 now; - - if (abstime == NULL) - return INFINITE; - - GetSystemTimeAsFileTime(&now.ft); - - /* - Calculate time left to abstime - - subtract start time from current time(values are in 100ns units) - - convert to millisec by dividing with 10000 - */ - millis= (abstime->tv.i64 - now.i64) / 10000; - - /* Don't allow the timeout to be negative */ - if (millis < 0) - return 0; - - /* - Make sure the calculated timeout does not exceed original timeout - value which could cause "wait for ever" if system time changes - */ - if (millis > abstime->max_timeout_msec) - millis= abstime->max_timeout_msec; - - if (millis > UINT_MAX) - millis= UINT_MAX; - - return (DWORD)millis; -} - - -/* - Old (pre-vista) implementation using events -*/ - -static int legacy_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) -{ - cond->waiting= 0; - InitializeCriticalSection(&cond->lock_waiting); - - cond->events[SIGNAL]= CreateEvent(NULL, /* no security */ - FALSE, /* auto-reset event */ - FALSE, /* non-signaled initially */ - NULL); /* unnamed */ - - /* Create a manual-reset event. */ - cond->events[BROADCAST]= CreateEvent(NULL, /* no security */ - TRUE, /* manual-reset */ - FALSE, /* non-signaled initially */ - NULL); /* unnamed */ - - - cond->broadcast_block_event= CreateEvent(NULL, /* no security */ - TRUE, /* manual-reset */ - TRUE, /* signaled initially */ - NULL); /* unnamed */ - - if( cond->events[SIGNAL] == NULL || - cond->events[BROADCAST] == NULL || - cond->broadcast_block_event == NULL ) - return ENOMEM; - return 0; -} - - -static int legacy_cond_destroy(pthread_cond_t *cond) -{ - DeleteCriticalSection(&cond->lock_waiting); - - if (CloseHandle(cond->events[SIGNAL]) == 0 || - CloseHandle(cond->events[BROADCAST]) == 0 || - CloseHandle(cond->broadcast_block_event) == 0) - return EINVAL; - return 0; -} - - -static int legacy_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - struct timespec *abstime) -{ - int result; - DWORD timeout; - - timeout= get_milliseconds(abstime); - /* - Block access if previous broadcast hasn't finished. - This is just for safety and should normally not - affect the total time spent in this function. - */ - WaitForSingleObject(cond->broadcast_block_event, INFINITE); - - EnterCriticalSection(&cond->lock_waiting); - cond->waiting++; - LeaveCriticalSection(&cond->lock_waiting); - - LeaveCriticalSection(mutex); - result= WaitForMultipleObjects(2, cond->events, FALSE, timeout); - - EnterCriticalSection(&cond->lock_waiting); - cond->waiting--; - - if (cond->waiting == 0) - { - /* - We're the last waiter to be notified or to stop waiting, so - reset the manual event. - */ - /* Close broadcast gate */ - ResetEvent(cond->events[BROADCAST]); - /* Open block gate */ - SetEvent(cond->broadcast_block_event); - } - LeaveCriticalSection(&cond->lock_waiting); - - EnterCriticalSection(mutex); - - return result == WAIT_TIMEOUT ? ETIMEDOUT : 0; -} - -static int legacy_cond_signal(pthread_cond_t *cond) -{ - EnterCriticalSection(&cond->lock_waiting); - - if(cond->waiting > 0) - SetEvent(cond->events[SIGNAL]); - - LeaveCriticalSection(&cond->lock_waiting); - - return 0; -} - - -static int legacy_cond_broadcast(pthread_cond_t *cond) -{ - EnterCriticalSection(&cond->lock_waiting); - /* - The mutex protect us from broadcasting if - there isn't any thread waiting to open the - block gate after this call has closed it. - */ - if(cond->waiting > 0) - { - /* Close block gate */ - ResetEvent(cond->broadcast_block_event); - /* Open broadcast gate */ - SetEvent(cond->events[BROADCAST]); - } - - LeaveCriticalSection(&cond->lock_waiting); - - return 0; -} - - -/* - Posix API functions. Just choose between native and legacy implementation. -*/ - -int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) -{ - /* - Once initialization is used here rather than in my_init(), to - 1) avoid my_init() pitfalls- undefined order in which initialization should - run - 2) be potentially useful C++ (in static constructors that run before main()) - 3) just to simplify the API. - Also, the overhead of my_pthread_once is very small. - */ - static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT; - my_pthread_once(&once_control, check_native_cond_availability); - - if (have_native_conditions) - { - my_InitializeConditionVariable(&cond->native_cond); - return 0; - } - else - return legacy_cond_init(cond, attr); -} - - -int pthread_cond_destroy(pthread_cond_t *cond) -{ - if (have_native_conditions) - return 0; /* no destroy function */ - else - return legacy_cond_destroy(cond); -} - - -int pthread_cond_broadcast(pthread_cond_t *cond) -{ - if (have_native_conditions) - { - my_WakeAllConditionVariable(&cond->native_cond); - return 0; - } - else - return legacy_cond_broadcast(cond); -} - - -int pthread_cond_signal(pthread_cond_t *cond) -{ - if (have_native_conditions) - { - my_WakeConditionVariable(&cond->native_cond); - return 0; - } - else - return legacy_cond_signal(cond); -} - - -int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - struct timespec *abstime) -{ - if (have_native_conditions) - { - DWORD timeout= get_milliseconds(abstime); - if (!my_SleepConditionVariableCS(&cond->native_cond, mutex, timeout)) - return ETIMEDOUT; - return 0; - } - else - return legacy_cond_timedwait(cond, mutex, abstime); -} - - -int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) -{ - return pthread_cond_timedwait(cond, mutex, NULL); -} - - -int pthread_attr_init(pthread_attr_t *connect_att) -{ - connect_att->dwStackSize = 0; - connect_att->dwCreatingFlag = 0; - return 0; -} - -int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack) -{ - connect_att->dwStackSize=stack; - return 0; -} - -int pthread_attr_destroy(pthread_attr_t *connect_att) -{ - bzero((uchar*) 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/dep/mysqllite/mysys/my_windac.c b/dep/mysqllite/mysys/my_windac.c deleted file mode 100644 index 0c924188623..00000000000 --- a/dep/mysqllite/mysys/my_windac.c +++ /dev/null @@ -1,223 +0,0 @@ -/* 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 - 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 "m_string.h" -#ifdef __WIN__ - -/* Windows NT/2000 discretionary access control utility functions. */ - -/* - Check if the operating system is built on NT technology. - - RETURN - 0 Windows 95/98/Me - 1 otherwise -*/ - -static my_bool is_nt() -{ - return GetVersion() < 0x80000000; -} - -/* - Auxilary structure to store pointers to the data which we need to keep - around while SECURITY_ATTRIBUTES is in use. -*/ - -typedef struct st_my_security_attr -{ - PSID everyone_sid; - PACL dacl; -} My_security_attr; - - -/* - Allocate and initialize SECURITY_ATTRIBUTES setting up access - rights for the owner and group `Everybody'. - - SYNOPSIS - my_security_attr_create() - psa [OUT] pointer to store the pointer to SA in - perror [OUT] pointer to store error message if there was an - error - owner_rights [IN] access rights for the owner - everyone_rights [IN] access rights for group Everybody - - DESCRIPTION - Set up the security attributes to provide clients with sufficient - access rights to a kernel object. We need this function - because if we simply grant all access to everybody (by installing - a NULL DACL) a mailicious user can attempt a denial of service - attack by taking ownership over the kernel object. Upon successful - return `psa' contains a pointer to SECUIRITY_ATTRIBUTES that can be used - to create kernel objects with proper access rights. - - RETURN - 0 success, psa is 0 or points to a valid SA structure, - perror is left intact - !0 error, SA is set to 0, error message is stored in perror -*/ - -int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror, - DWORD owner_rights, DWORD everyone_rights) -{ - /* Top-level SID authority */ - SID_IDENTIFIER_AUTHORITY world_auth= SECURITY_WORLD_SID_AUTHORITY; - PSID everyone_sid= 0; - HANDLE htoken= 0; - SECURITY_ATTRIBUTES *sa= 0; - PACL dacl= 0; - DWORD owner_token_length, dacl_length; - SECURITY_DESCRIPTOR *sd; - PTOKEN_USER owner_token; - PSID owner_sid; - My_security_attr *attr; - - if (! is_nt()) - { - *psa= 0; - return 0; - } - - /* - Get SID of Everyone group. Easier to retrieve all SIDs each time - this function is called than worry about thread safety. - */ - if (! AllocateAndInitializeSid(&world_auth, 1, SECURITY_WORLD_RID, - 0, 0, 0, 0, 0, 0, 0, &everyone_sid)) - { - *perror= "Failed to retrieve the SID of Everyone group"; - goto error; - } - - /* - Get SID of the owner. Using GetSecurityInfo this task can be done - in just one call instead of five, but GetSecurityInfo declared in - aclapi.h, so I hesitate to use it. - SIC: OpenThreadToken works only if there is an active impersonation - token, hence OpenProcessToken is used. - */ - if (! OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken)) - { - *perror= "Failed to retrieve thread access token"; - goto error; - } - GetTokenInformation(htoken, TokenUser, 0, 0, &owner_token_length); - - if (! my_multi_malloc(MYF(MY_WME), - &sa, ALIGN_SIZE(sizeof(SECURITY_ATTRIBUTES)) + - sizeof(My_security_attr), - &sd, sizeof(SECURITY_DESCRIPTOR), - &owner_token, owner_token_length, - 0)) - { - *perror= "Failed to allocate memory for SECURITY_ATTRIBUTES"; - goto error; - } - bzero(owner_token, owner_token_length); - if (! GetTokenInformation(htoken, TokenUser, owner_token, - owner_token_length, &owner_token_length)) - { - *perror= "GetTokenInformation failed"; - goto error; - } - owner_sid= owner_token->User.Sid; - - if (! IsValidSid(owner_sid)) - { - *perror= "IsValidSid failed"; - goto error; - } - - /* Calculate the amount of memory that must be allocated for the DACL */ - dacl_length= sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD)) * 2 + - GetLengthSid(everyone_sid) + GetLengthSid(owner_sid); - - /* Create an ACL */ - if (! (dacl= (PACL) my_malloc(dacl_length, MYF(MY_ZEROFILL|MY_WME)))) - { - *perror= "Failed to allocate memory for DACL"; - goto error; - } - if (! InitializeAcl(dacl, dacl_length, ACL_REVISION)) - { - *perror= "Failed to initialize DACL"; - goto error; - } - if (! AddAccessAllowedAce(dacl, ACL_REVISION, everyone_rights, everyone_sid)) - { - *perror= "Failed to set up DACL"; - goto error; - } - if (! AddAccessAllowedAce(dacl, ACL_REVISION, owner_rights, owner_sid)) - { - *perror= "Failed to set up DACL"; - goto error; - } - if (! InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) - { - *perror= "Could not initialize security descriptor"; - goto error; - } - if (! SetSecurityDescriptorDacl(sd, TRUE, dacl, FALSE)) - { - *perror= "Failed to install DACL"; - goto error; - } - - sa->nLength= sizeof(*sa); - sa->bInheritHandle= TRUE; - sa->lpSecurityDescriptor= sd; - /* Save pointers to everyone_sid and dacl to be able to clean them up */ - attr= (My_security_attr*) (((char*) sa) + ALIGN_SIZE(sizeof(*sa))); - attr->everyone_sid= everyone_sid; - attr->dacl= dacl; - *psa= sa; - - CloseHandle(htoken); - return 0; -error: - if (everyone_sid) - FreeSid(everyone_sid); - if (htoken) - CloseHandle(htoken); - my_free(sa); - my_free(dacl); - *psa= 0; - return 1; -} - -/* - Cleanup security attributes freeing used memory. - - SYNOPSIS - my_security_attr_free() - sa security attributes -*/ - -void my_security_attr_free(SECURITY_ATTRIBUTES *sa) -{ - if (sa) - { - My_security_attr *attr= (My_security_attr*) - (((char*)sa) + ALIGN_SIZE(sizeof(*sa))); - FreeSid(attr->everyone_sid); - my_free(attr->dacl); - my_free(sa); - } -} - -#endif /* __WIN__ */ diff --git a/dep/mysqllite/mysys/my_winerr.c b/dep/mysqllite/mysys/my_winerr.c deleted file mode 100644 index 534078b6737..00000000000 --- a/dep/mysqllite/mysys/my_winerr.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (C) 2008 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 */ - -/* - Convert Windows API error (GetLastError() to Posix equivalent (errno) - The exported function my_osmaperr() is modelled after and borrows - heavily from undocumented _dosmaperr()(found of the static Microsoft C runtime). -*/ - -#include <my_global.h> -#include <my_sys.h> - - -struct errentry -{ - unsigned long oscode; /* OS return value */ - int sysv_errno; /* System V error code */ -}; - -static struct errentry errtable[]= { - { ERROR_INVALID_FUNCTION, EINVAL }, /* 1 */ - { ERROR_FILE_NOT_FOUND, ENOENT }, /* 2 */ - { ERROR_PATH_NOT_FOUND, ENOENT }, /* 3 */ - { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, /* 4 */ - { ERROR_ACCESS_DENIED, EACCES }, /* 5 */ - { ERROR_INVALID_HANDLE, EBADF }, /* 6 */ - { ERROR_ARENA_TRASHED, ENOMEM }, /* 7 */ - { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, /* 8 */ - { ERROR_INVALID_BLOCK, ENOMEM }, /* 9 */ - { ERROR_BAD_ENVIRONMENT, E2BIG }, /* 10 */ - { ERROR_BAD_FORMAT, ENOEXEC }, /* 11 */ - { ERROR_INVALID_ACCESS, EINVAL }, /* 12 */ - { ERROR_INVALID_DATA, EINVAL }, /* 13 */ - { ERROR_INVALID_DRIVE, ENOENT }, /* 15 */ - { ERROR_CURRENT_DIRECTORY, EACCES }, /* 16 */ - { ERROR_NOT_SAME_DEVICE, EXDEV }, /* 17 */ - { ERROR_NO_MORE_FILES, ENOENT }, /* 18 */ - { ERROR_LOCK_VIOLATION, EACCES }, /* 33 */ - { ERROR_BAD_NETPATH, ENOENT }, /* 53 */ - { ERROR_NETWORK_ACCESS_DENIED, EACCES }, /* 65 */ - { ERROR_BAD_NET_NAME, ENOENT }, /* 67 */ - { ERROR_FILE_EXISTS, EEXIST }, /* 80 */ - { ERROR_CANNOT_MAKE, EACCES }, /* 82 */ - { ERROR_FAIL_I24, EACCES }, /* 83 */ - { ERROR_INVALID_PARAMETER, EINVAL }, /* 87 */ - { ERROR_NO_PROC_SLOTS, EAGAIN }, /* 89 */ - { ERROR_DRIVE_LOCKED, EACCES }, /* 108 */ - { ERROR_BROKEN_PIPE, EPIPE }, /* 109 */ - { ERROR_DISK_FULL, ENOSPC }, /* 112 */ - { ERROR_INVALID_TARGET_HANDLE, EBADF }, /* 114 */ - { ERROR_INVALID_HANDLE, EINVAL }, /* 124 */ - { ERROR_WAIT_NO_CHILDREN, ECHILD }, /* 128 */ - { ERROR_CHILD_NOT_COMPLETE, ECHILD }, /* 129 */ - { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, /* 130 */ - { ERROR_NEGATIVE_SEEK, EINVAL }, /* 131 */ - { ERROR_SEEK_ON_DEVICE, EACCES }, /* 132 */ - { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, /* 145 */ - { ERROR_NOT_LOCKED, EACCES }, /* 158 */ - { ERROR_BAD_PATHNAME, ENOENT }, /* 161 */ - { ERROR_MAX_THRDS_REACHED, EAGAIN }, /* 164 */ - { ERROR_LOCK_FAILED, EACCES }, /* 167 */ - { ERROR_ALREADY_EXISTS, EEXIST }, /* 183 */ - { ERROR_FILENAME_EXCED_RANGE, ENOENT }, /* 206 */ - { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, /* 215 */ - { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } /* 1816 */ -}; - -/* size of the table */ -#define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0])) - -/* The following two constants must be the minimum and maximum -values in the (contiguous) range of Exec Failure errors. */ -#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG -#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN - -/* These are the low and high value in the range of errors that are -access violations */ -#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT -#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED - - -static int get_errno_from_oserr(unsigned long oserrno) -{ - int i; - - /* check the table for the OS error code */ - for (i= 0; i < ERRTABLESIZE; ++i) - { - if (oserrno == errtable[i].oscode) - { - return errtable[i].sysv_errno; - } - } - - /* The error code wasn't in the table. We check for a range of */ - /* EACCES errors or exec failure errors (ENOEXEC). Otherwise */ - /* EINVAL is returned. */ - - if (oserrno >= MIN_EACCES_RANGE && oserrno <= MAX_EACCES_RANGE) - return EACCES; - else if (oserrno >= MIN_EXEC_ERROR && oserrno <= MAX_EXEC_ERROR) - return ENOEXEC; - else - return EINVAL; -} - -/* Set errno corresponsing to GetLastError() value */ -void my_osmaperr ( unsigned long oserrno) -{ - errno= get_errno_from_oserr(oserrno); -} diff --git a/dep/mysqllite/mysys/my_winfile.c b/dep/mysqllite/mysys/my_winfile.c deleted file mode 100644 index 4d80d774dad..00000000000 --- a/dep/mysqllite/mysys/my_winfile.c +++ /dev/null @@ -1,681 +0,0 @@ -/* Copyright (C) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc - -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 */ - -/* - The purpose of this file is to provide implementation of file IO routines on - Windows that can be thought as drop-in replacement for corresponding C runtime - functionality. - - Compared to Windows CRT, this one - - does not have the same file descriptor - limitation (default is 16384 and can be increased further, whereas CRT poses - a hard limit of 2048 file descriptors) - - the file operations are not serialized - - positional IO pread/pwrite is ported here. - - no text mode for files, all IO is "binary" - - Naming convention: - All routines are prefixed with my_win_, e.g Posix open() is implemented with - my_win_open() - - Implemented are - - POSIX routines(e.g open, read, lseek ...) - - Some ANSI C stream routines (fopen, fdopen, fileno, fclose) - - Windows CRT equvalients (my_get_osfhandle, open_osfhandle) - - Worth to note: - - File descriptors used here are located in a range that is not compatible - with CRT on purpose. Attempt to use a file descriptor from Windows CRT library - range in my_win_* function will be punished with DBUG_ASSERT() - - - File streams (FILE *) are actually from the C runtime. The routines provided - here are useful only in scernarios that use low-level IO with my_win_fileno() -*/ - -#ifdef _WIN32 - -#include "mysys_priv.h" -#include <share.h> -#include <sys/stat.h> - -/* Associates a file descriptor with an existing operating-system file handle.*/ -File my_open_osfhandle(HANDLE handle, int oflag) -{ - int offset= -1; - uint i; - DBUG_ENTER("my_open_osfhandle"); - - mysql_mutex_lock(&THR_LOCK_open); - for(i= MY_FILE_MIN; i < my_file_limit;i++) - { - if(my_file_info[i].fhandle == 0) - { - struct st_my_file_info *finfo= &(my_file_info[i]); - finfo->type= FILE_BY_OPEN; - finfo->fhandle= handle; - finfo->oflag= oflag; - offset= i; - break; - } - } - mysql_mutex_unlock(&THR_LOCK_open); - if(offset == -1) - errno= EMFILE; /* to many file handles open */ - DBUG_RETURN(offset); -} - - -static void invalidate_fd(File fd) -{ - DBUG_ENTER("invalidate_fd"); - DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); - my_file_info[fd].fhandle= 0; - DBUG_VOID_RETURN; -} - - -/* Get Windows handle for a file descriptor */ -HANDLE my_get_osfhandle(File fd) -{ - DBUG_ENTER("my_get_osfhandle"); - DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); - DBUG_RETURN(my_file_info[fd].fhandle); -} - - -static int my_get_open_flags(File fd) -{ - DBUG_ENTER("my_get_open_flags"); - DBUG_ASSERT(fd >= MY_FILE_MIN && fd < (int)my_file_limit); - DBUG_RETURN(my_file_info[fd].oflag); -} - - -/* - Open a file with sharing. Similar to _sopen() from libc, but allows managing - share delete on win32 - - SYNOPSIS - my_win_sopen() - path file name - oflag operation flags - shflag share flag - pmode permission flags - - RETURN VALUE - File descriptor of opened file if success - -1 and sets errno if fails. -*/ - -File my_win_sopen(const char *path, int oflag, int shflag, int pmode) -{ - int fh; /* handle of opened file */ - int mask; - HANDLE osfh; /* OS handle of opened file */ - DWORD fileaccess; /* OS file access (requested) */ - DWORD fileshare; /* OS file sharing mode */ - DWORD filecreate; /* OS method of opening/creating */ - DWORD fileattrib; /* OS file attribute flags */ - SECURITY_ATTRIBUTES SecurityAttributes; - - DBUG_ENTER("my_win_sopen"); - - if (check_if_legal_filename(path)) - { - errno= EACCES; - DBUG_RETURN(-1); - } - SecurityAttributes.nLength= sizeof(SecurityAttributes); - SecurityAttributes.lpSecurityDescriptor= NULL; - SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT); - - /* decode the access flags */ - switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { - case _O_RDONLY: /* read access */ - fileaccess= GENERIC_READ; - break; - case _O_WRONLY: /* write access */ - fileaccess= GENERIC_WRITE; - break; - case _O_RDWR: /* read and write access */ - fileaccess= GENERIC_READ | GENERIC_WRITE; - break; - default: /* error, bad oflag */ - errno= EINVAL; - DBUG_RETURN(-1); - } - - /* decode sharing flags */ - switch (shflag) { - case _SH_DENYRW: /* exclusive access except delete */ - fileshare= FILE_SHARE_DELETE; - break; - case _SH_DENYWR: /* share read and delete access */ - fileshare= FILE_SHARE_READ | FILE_SHARE_DELETE; - break; - case _SH_DENYRD: /* share write and delete access */ - fileshare= FILE_SHARE_WRITE | FILE_SHARE_DELETE; - break; - case _SH_DENYNO: /* share read, write and delete access */ - fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; - break; - case _SH_DENYRWD: /* exclusive access */ - fileshare= 0L; - break; - case _SH_DENYWRD: /* share read access */ - fileshare= FILE_SHARE_READ; - break; - case _SH_DENYRDD: /* share write access */ - fileshare= FILE_SHARE_WRITE; - break; - case _SH_DENYDEL: /* share read and write access */ - fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE; - break; - default: /* error, bad shflag */ - errno= EINVAL; - DBUG_RETURN(-1); - } - - /* decode open/create method flags */ - switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) { - case 0: - case _O_EXCL: /* ignore EXCL w/o CREAT */ - filecreate= OPEN_EXISTING; - break; - - case _O_CREAT: - filecreate= OPEN_ALWAYS; - break; - - case _O_CREAT | _O_EXCL: - case _O_CREAT | _O_TRUNC | _O_EXCL: - filecreate= CREATE_NEW; - break; - - case _O_TRUNC: - case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */ - filecreate= TRUNCATE_EXISTING; - break; - - case _O_CREAT | _O_TRUNC: - filecreate= CREATE_ALWAYS; - break; - - default: - /* this can't happen ... all cases are covered */ - errno= EINVAL; - DBUG_RETURN(-1); - } - - /* decode file attribute flags if _O_CREAT was specified */ - fileattrib= FILE_ATTRIBUTE_NORMAL; /* default */ - if (oflag & _O_CREAT) - { - _umask((mask= _umask(0))); - - if (!((pmode & ~mask) & _S_IWRITE)) - fileattrib= FILE_ATTRIBUTE_READONLY; - } - - /* Set temporary file (delete-on-close) attribute if requested. */ - if (oflag & _O_TEMPORARY) - { - fileattrib|= FILE_FLAG_DELETE_ON_CLOSE; - fileaccess|= DELETE; - } - - /* Set temporary file (delay-flush-to-disk) attribute if requested.*/ - if (oflag & _O_SHORT_LIVED) - fileattrib|= FILE_ATTRIBUTE_TEMPORARY; - - /* Set sequential or random access attribute if requested. */ - if (oflag & _O_SEQUENTIAL) - fileattrib|= FILE_FLAG_SEQUENTIAL_SCAN; - else if (oflag & _O_RANDOM) - fileattrib|= FILE_FLAG_RANDOM_ACCESS; - - /* try to open/create the file */ - if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes, - filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE) - { - /* - OS call to open/create file failed! map the error, release - the lock, and return -1. note that it's not necessary to - call _free_osfhnd (it hasn't been used yet). - */ - my_osmaperr(GetLastError()); /* map error */ - DBUG_RETURN(-1); /* return error to caller */ - } - - if ((fh= my_open_osfhandle(osfh, - oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1) - { - CloseHandle(osfh); - } - - DBUG_RETURN(fh); /* return handle */ -} - - -File my_win_open(const char *path, int flags) -{ - DBUG_ENTER("my_win_open"); - DBUG_RETURN(my_win_sopen((char *) path, flags | _O_BINARY, _SH_DENYNO, - _S_IREAD | S_IWRITE)); -} - - -int my_win_close(File fd) -{ - DBUG_ENTER("my_win_close"); - if(CloseHandle(my_get_osfhandle(fd))) - { - invalidate_fd(fd); - DBUG_RETURN(0); - } - my_osmaperr(GetLastError()); - DBUG_RETURN(-1); -} - - -size_t my_win_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset) -{ - DWORD nBytesRead; - HANDLE hFile; - OVERLAPPED ov= {0}; - LARGE_INTEGER li; - - DBUG_ENTER("my_win_pread"); - - if(!Count) - DBUG_RETURN(0); -#ifdef _WIN64 - if(Count > UINT_MAX) - Count= UINT_MAX; -#endif - - hFile= (HANDLE)my_get_osfhandle(Filedes); - li.QuadPart= offset; - ov.Offset= li.LowPart; - ov.OffsetHigh= li.HighPart; - - if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, &ov)) - { - DWORD lastError= GetLastError(); - /* - ERROR_BROKEN_PIPE is returned when no more data coming - through e.g. a command pipe in windows : see MSDN on ReadFile. - */ - if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE) - DBUG_RETURN(0); /*return 0 at EOF*/ - my_osmaperr(lastError); - DBUG_RETURN((size_t)-1); - } - DBUG_RETURN(nBytesRead); -} - - -size_t my_win_read(File Filedes, uchar *Buffer, size_t Count) -{ - DWORD nBytesRead; - HANDLE hFile; - - DBUG_ENTER("my_win_read"); - if(!Count) - DBUG_RETURN(0); -#ifdef _WIN64 - if(Count > UINT_MAX) - Count= UINT_MAX; -#endif - - hFile= (HANDLE)my_get_osfhandle(Filedes); - - if(!ReadFile(hFile, Buffer, (DWORD)Count, &nBytesRead, NULL)) - { - DWORD lastError= GetLastError(); - /* - ERROR_BROKEN_PIPE is returned when no more data coming - through e.g. a command pipe in windows : see MSDN on ReadFile. - */ - if(lastError == ERROR_HANDLE_EOF || lastError == ERROR_BROKEN_PIPE) - DBUG_RETURN(0); /*return 0 at EOF*/ - my_osmaperr(lastError); - DBUG_RETURN((size_t)-1); - } - DBUG_RETURN(nBytesRead); -} - - -size_t my_win_pwrite(File Filedes, const uchar *Buffer, size_t Count, - my_off_t offset) -{ - DWORD nBytesWritten; - HANDLE hFile; - OVERLAPPED ov= {0}; - LARGE_INTEGER li; - - DBUG_ENTER("my_win_pwrite"); - DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count: %llu, offset: %llu", - Filedes, Buffer, (ulonglong)Count, (ulonglong)offset)); - - if(!Count) - DBUG_RETURN(0); - -#ifdef _WIN64 - if(Count > UINT_MAX) - Count= UINT_MAX; -#endif - - hFile= (HANDLE)my_get_osfhandle(Filedes); - li.QuadPart= offset; - ov.Offset= li.LowPart; - ov.OffsetHigh= li.HighPart; - - if(!WriteFile(hFile, Buffer, (DWORD)Count, &nBytesWritten, &ov)) - { - my_osmaperr(GetLastError()); - DBUG_RETURN((size_t)-1); - } - else - DBUG_RETURN(nBytesWritten); -} - - -my_off_t my_win_lseek(File fd, my_off_t pos, int whence) -{ - LARGE_INTEGER offset; - LARGE_INTEGER newpos; - - DBUG_ENTER("my_win_lseek"); - - /* Check compatibility of Windows and Posix seek constants */ - compile_time_assert(FILE_BEGIN == SEEK_SET && FILE_CURRENT == SEEK_CUR - && FILE_END == SEEK_END); - - offset.QuadPart= pos; - if(!SetFilePointerEx(my_get_osfhandle(fd), offset, &newpos, whence)) - { - my_osmaperr(GetLastError()); - newpos.QuadPart= -1; - } - DBUG_RETURN(newpos.QuadPart); -} - - -#ifndef FILE_WRITE_TO_END_OF_FILE -#define FILE_WRITE_TO_END_OF_FILE 0xffffffff -#endif -size_t my_win_write(File fd, const uchar *Buffer, size_t Count) -{ - DWORD nWritten; - OVERLAPPED ov; - OVERLAPPED *pov= NULL; - HANDLE hFile; - - DBUG_ENTER("my_win_write"); - DBUG_PRINT("my",("Filedes: %d, Buffer: %p, Count %llu", fd, Buffer, - (ulonglong)Count)); - - if(!Count) - DBUG_RETURN(0); - -#ifdef _WIN64 - if(Count > UINT_MAX) - Count= UINT_MAX; -#endif - - if(my_get_open_flags(fd) & _O_APPEND) - { - /* - Atomic append to the end of file is is done by special initialization of - the OVERLAPPED structure. See MSDN WriteFile documentation for more info. - */ - memset(&ov, 0, sizeof(ov)); - ov.Offset= FILE_WRITE_TO_END_OF_FILE; - ov.OffsetHigh= -1; - pov= &ov; - } - - hFile= my_get_osfhandle(fd); - if(!WriteFile(hFile, Buffer, (DWORD)Count, &nWritten, pov)) - { - my_osmaperr(GetLastError()); - DBUG_RETURN((size_t)-1); - } - DBUG_RETURN(nWritten); -} - - -int my_win_chsize(File fd, my_off_t newlength) -{ - HANDLE hFile; - LARGE_INTEGER length; - DBUG_ENTER("my_win_chsize"); - - hFile= (HANDLE) my_get_osfhandle(fd); - length.QuadPart= newlength; - if (!SetFilePointerEx(hFile, length , NULL , FILE_BEGIN)) - goto err; - if (!SetEndOfFile(hFile)) - goto err; - DBUG_RETURN(0); -err: - my_osmaperr(GetLastError()); - my_errno= errno; - DBUG_RETURN(-1); -} - - -/* Get the file descriptor for stdin,stdout or stderr */ -static File my_get_stdfile_descriptor(FILE *stream) -{ - HANDLE hFile; - DWORD nStdHandle; - DBUG_ENTER("my_get_stdfile_descriptor"); - - if(stream == stdin) - nStdHandle= STD_INPUT_HANDLE; - else if(stream == stdout) - nStdHandle= STD_OUTPUT_HANDLE; - else if(stream == stderr) - nStdHandle= STD_ERROR_HANDLE; - else - DBUG_RETURN(-1); - - hFile= GetStdHandle(nStdHandle); - if(hFile != INVALID_HANDLE_VALUE) - DBUG_RETURN(my_open_osfhandle(hFile, 0)); - DBUG_RETURN(-1); -} - - -File my_win_fileno(FILE *file) -{ - HANDLE hFile= (HANDLE)_get_osfhandle(fileno(file)); - int retval= -1; - uint i; - - DBUG_ENTER("my_win_fileno"); - - for(i= MY_FILE_MIN; i < my_file_limit; i++) - { - if(my_file_info[i].fhandle == hFile) - { - retval= i; - break; - } - } - if(retval == -1) - /* try std stream */ - DBUG_RETURN(my_get_stdfile_descriptor(file)); - DBUG_RETURN(retval); -} - - -FILE *my_win_fopen(const char *filename, const char *type) -{ - FILE *file; - int flags= 0; - DBUG_ENTER("my_win_open"); - - /* - If we are not creating, then we need to use my_access to make sure - the file exists since Windows doesn't handle files like "com1.sym" - very well - */ - if (check_if_legal_filename(filename)) - { - errno= EACCES; - DBUG_RETURN(NULL); - } - - file= fopen(filename, type); - if(!file) - DBUG_RETURN(NULL); - - if(strchr(type,'a') != NULL) - flags= O_APPEND; - - /* - Register file handle in my_table_info. - Necessary for my_fileno() - */ - if(my_open_osfhandle((HANDLE)_get_osfhandle(fileno(file)), flags) < 0) - { - fclose(file); - DBUG_RETURN(NULL); - } - DBUG_RETURN(file); -} - - -FILE * my_win_fdopen(File fd, const char *type) -{ - FILE *file; - int crt_fd; - int flags= 0; - - DBUG_ENTER("my_win_fdopen"); - - if(strchr(type,'a') != NULL) - flags= O_APPEND; - /* Convert OS file handle to CRT file descriptor and then call fdopen*/ - crt_fd= _open_osfhandle((intptr_t)my_get_osfhandle(fd), flags); - if(crt_fd < 0) - file= NULL; - else - file= fdopen(crt_fd, type); - DBUG_RETURN(file); -} - - -int my_win_fclose(FILE *file) -{ - File fd; - - DBUG_ENTER("my_win_close"); - fd= my_fileno(file); - if(fd < 0) - DBUG_RETURN(-1); - if(fclose(file) < 0) - DBUG_RETURN(-1); - invalidate_fd(fd); - DBUG_RETURN(0); -} - - - -/* - Quick and dirty my_fstat() implementation for Windows. - Use CRT fstat on temporarily allocated file descriptor. - Patch file size, because size that fstat returns is not - reliable (may be outdated) -*/ -int my_win_fstat(File fd, struct _stati64 *buf) -{ - int crt_fd; - int retval; - HANDLE hFile, hDup; - - DBUG_ENTER("my_win_fstat"); - - hFile= my_get_osfhandle(fd); - if(!DuplicateHandle( GetCurrentProcess(), hFile, GetCurrentProcess(), - &hDup ,0,FALSE,DUPLICATE_SAME_ACCESS)) - { - my_osmaperr(GetLastError()); - DBUG_RETURN(-1); - } - if ((crt_fd= _open_osfhandle((intptr_t)hDup,0)) < 0) - DBUG_RETURN(-1); - - retval= _fstati64(crt_fd, buf); - if(retval == 0) - { - /* File size returned by stat is not accurate (may be outdated), fix it*/ - GetFileSizeEx(hDup, (PLARGE_INTEGER) (&(buf->st_size))); - } - _close(crt_fd); - DBUG_RETURN(retval); -} - - - -int my_win_stat( const char *path, struct _stati64 *buf) -{ - DBUG_ENTER("my_win_stat"); - if(_stati64( path, buf) == 0) - { - /* File size returned by stat is not accurate (may be outdated), fix it*/ - WIN32_FILE_ATTRIBUTE_DATA data; - if (GetFileAttributesEx(path, GetFileExInfoStandard, &data)) - { - LARGE_INTEGER li; - li.LowPart= data.nFileSizeLow; - li.HighPart= data.nFileSizeHigh; - buf->st_size= li.QuadPart; - } - DBUG_RETURN(0); - } - DBUG_RETURN(-1); -} - - - -int my_win_fsync(File fd) -{ - DBUG_ENTER("my_win_fsync"); - if(FlushFileBuffers(my_get_osfhandle(fd))) - DBUG_RETURN(0); - my_osmaperr(GetLastError()); - DBUG_RETURN(-1); -} - - - -int my_win_dup(File fd) -{ - HANDLE hDup; - DBUG_ENTER("my_win_dup"); - if (DuplicateHandle(GetCurrentProcess(), my_get_osfhandle(fd), - GetCurrentProcess(), &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) - { - DBUG_RETURN(my_open_osfhandle(hDup, my_get_open_flags(fd))); - } - my_osmaperr(GetLastError()); - DBUG_RETURN(-1); -} - -#endif /*_WIN32*/ diff --git a/dep/mysqllite/mysys/my_winthread.c b/dep/mysqllite/mysys/my_winthread.c deleted file mode 100644 index 49534370a2f..00000000000 --- a/dep/mysqllite/mysys/my_winthread.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/***************************************************************************** -** Simulation of posix threads calls for Windows -*****************************************************************************/ -#if defined (_WIN32) -/* SAFE_MUTEX will not work until the thread structure is up to date */ -#undef SAFE_MUTEX -#include "mysys_priv.h" -#include <process.h> -#include <signal.h> - -static void install_sigabrt_handler(void); - -struct thread_start_parameter -{ - pthread_handler func; - void *arg; -}; - -/** - Adapter to @c pthread_mutex_trylock() - - @retval 0 Mutex was acquired - @retval EBUSY Mutex was already locked by a thread - */ -int -win_pthread_mutex_trylock(pthread_mutex_t *mutex) -{ - if (TryEnterCriticalSection(mutex)) - { - /* Don't allow recursive lock */ - if (mutex->RecursionCount > 1){ - LeaveCriticalSection(mutex); - return EBUSY; - } - return 0; - } - return EBUSY; -} - -static unsigned int __stdcall pthread_start(void *p) -{ - struct thread_start_parameter *par= (struct thread_start_parameter *)p; - pthread_handler func= par->func; - void *arg= par->arg; - free(p); - (*func)(arg); - return 0; -} - - -int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr, - pthread_handler func, void *param) -{ - uintptr_t handle; - struct thread_start_parameter *par; - unsigned int stack_size; - DBUG_ENTER("pthread_create"); - - par= (struct thread_start_parameter *)malloc(sizeof(*par)); - if (!par) - goto error_return; - - par->func= func; - par->arg= param; - stack_size= attr?attr->dwStackSize:0; - - handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id); - if (!handle) - goto error_return; - DBUG_PRINT("info", ("thread id=%u",*thread_id)); - - /* Do not need thread handle, close it */ - CloseHandle((HANDLE)handle); - DBUG_RETURN(0); - -error_return: - DBUG_PRINT("error", - ("Can't create thread to handle request (error %d)",errno)); - DBUG_RETURN(-1); -} - - -void pthread_exit(void *a) -{ - _endthreadex(0); -} - -int pthread_join(pthread_t thread, void **value_ptr) -{ - DWORD ret; - HANDLE handle; - - handle= OpenThread(SYNCHRONIZE, FALSE, thread); - if (!handle) - { - errno= EINVAL; - goto error_return; - } - - ret= WaitForSingleObject(handle, INFINITE); - - if(ret != WAIT_OBJECT_0) - { - errno= EINVAL; - goto error_return; - } - - CloseHandle(handle); - return 0; - -error_return: - if(handle) - CloseHandle(handle); - return -1; -} - -int pthread_cancel(pthread_t thread) -{ - - HANDLE handle= 0; - BOOL ok= FALSE; - - handle= OpenThread(THREAD_TERMINATE, FALSE, thread); - if (handle) - { - ok= TerminateThread(handle,0); - CloseHandle(handle); - } - if (ok) - return 0; - - errno= EINVAL; - return -1; -} - -/* - One time initialization. For simplicity, we assume initializer thread - does not exit within init_routine(). -*/ -int my_pthread_once(my_pthread_once_t *once_control, - void (*init_routine)(void)) -{ - LONG state; - - /* - Do "dirty" read to find out if initialization is already done, to - save an interlocked operation in common case. Memory barriers are ensured by - Visual C++ volatile implementation. - */ - if (*once_control == MY_PTHREAD_ONCE_DONE) - return 0; - - state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS, - MY_PTHREAD_ONCE_INIT); - - switch(state) - { - case MY_PTHREAD_ONCE_INIT: - /* This is initializer thread */ - (*init_routine)(); - *once_control= MY_PTHREAD_ONCE_DONE; - break; - - case MY_PTHREAD_ONCE_INPROGRESS: - /* init_routine in progress. Wait for its completion */ - while(*once_control == MY_PTHREAD_ONCE_INPROGRESS) - { - Sleep(1); - } - break; - case MY_PTHREAD_ONCE_DONE: - /* Nothing to do */ - break; - } - return 0; -} -#endif diff --git a/dep/mysqllite/mysys/my_write.c b/dep/mysqllite/mysys/my_write.c deleted file mode 100644 index 64f7546620f..00000000000 --- a/dep/mysqllite/mysys/my_write.c +++ /dev/null @@ -1,100 +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" -#include <errno.h> - - - /* Write a chunk of bytes to a file */ - -size_t my_write(File Filedes, const uchar *Buffer, size_t Count, myf MyFlags) -{ - size_t writtenbytes, written; - uint errors; - DBUG_ENTER("my_write"); - DBUG_PRINT("my",("fd: %d Buffer: %p Count: %lu MyFlags: %d", - Filedes, Buffer, (ulong) Count, MyFlags)); - errors= 0; written= 0; - - /* The behavior of write(fd, buf, 0) is not portable */ - if (unlikely(!Count)) - DBUG_RETURN(0); - - for (;;) - { -#ifdef _WIN32 - writtenbytes= my_win_write(Filedes, Buffer, Count); -#else - writtenbytes= write(Filedes, Buffer, Count); -#endif - if (writtenbytes == Count) - break; - if (writtenbytes != (size_t) -1) - { /* Safeguard */ - written+= writtenbytes; - Buffer+= writtenbytes; - Count-= writtenbytes; - } - my_errno= errno; - DBUG_PRINT("error",("Write only %ld bytes, error: %d", - (long) writtenbytes, my_errno)); -#ifndef NO_BACKGROUND - if (my_thread_var->abort) - MyFlags&= ~ MY_WAIT_IF_FULL; /* End if aborted by user */ - - if ((my_errno == ENOSPC || my_errno == EDQUOT) && - (MyFlags & MY_WAIT_IF_FULL)) - { - wait_for_free_space(my_filename(Filedes), errors); - errors++; - continue; - } - - if ((writtenbytes == 0 || writtenbytes == (size_t) -1)) - { - if (my_errno == EINTR) - { - DBUG_PRINT("debug", ("my_write() was interrupted and returned %ld", - (long) writtenbytes)); - continue; /* Interrupted */ - } - - if (!writtenbytes && !errors++) /* Retry once */ - { - /* We may come here if the file quota is exeeded */ - errno= EFBIG; /* Assume this is the error */ - continue; - } - } - else - continue; /* Retry */ -#endif - if (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),my_errno); - } - DBUG_RETURN(MY_FILE_ERROR); /* Error on read */ - } - else - break; /* Return bytes written */ - } - if (MyFlags & (MY_NABP | MY_FNABP)) - DBUG_RETURN(0); /* Want only errors */ - DBUG_RETURN(writtenbytes+written); -} /* my_write */ diff --git a/dep/mysqllite/mysys/mysys_priv.h b/dep/mysqllite/mysys/mysys_priv.h deleted file mode 100644 index 4e642b7e3d3..00000000000 --- a/dep/mysqllite/mysys/mysys_priv.h +++ /dev/null @@ -1,107 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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_sys.h> - -#ifdef USE_SYSTEM_WRAPPERS -#include "system_wrappers.h" -#endif - -#ifdef HAVE_GETRUSAGE -#include <sys/resource.h> -#endif - -#include <my_pthread.h> - -#ifdef HAVE_PSI_INTERFACE - -#if !defined(HAVE_PREAD) && !defined(_WIN32) -extern PSI_mutex_key key_my_file_info_mutex; -#endif /* !defined(HAVE_PREAD) && !defined(_WIN32) */ - -#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) -extern PSI_mutex_key key_LOCK_localtime_r; -#endif /* !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R) */ - -#ifndef HAVE_GETHOSTBYNAME_R -extern PSI_mutex_key key_LOCK_gethostbyname_r; -#endif /* HAVE_GETHOSTBYNAME_R */ - -extern PSI_mutex_key key_BITMAP_mutex, key_IO_CACHE_append_buffer_lock, - key_IO_CACHE_SHARE_mutex, key_KEY_CACHE_cache_lock, key_LOCK_alarm, - key_my_thread_var_mutex, key_THR_LOCK_charset, key_THR_LOCK_heap, - key_THR_LOCK_isam, key_THR_LOCK_lock, key_THR_LOCK_malloc, - key_THR_LOCK_mutex, key_THR_LOCK_myisam, key_THR_LOCK_net, - key_THR_LOCK_open, key_THR_LOCK_threads, key_THR_LOCK_time, - key_TMPDIR_mutex, key_THR_LOCK_myisam_mmap; - -extern PSI_cond_key key_COND_alarm, key_IO_CACHE_SHARE_cond, - key_IO_CACHE_SHARE_cond_writer, key_my_thread_var_suspend, - key_THR_COND_threads; - -#ifdef USE_ALARM_THREAD -extern PSI_thread_key key_thread_alarm; -#endif /* USE_ALARM_THREAD */ - -#endif /* HAVE_PSI_INTERFACE */ - -extern mysql_mutex_t THR_LOCK_malloc, THR_LOCK_open, THR_LOCK_keycache; -extern mysql_mutex_t THR_LOCK_lock, THR_LOCK_isam, THR_LOCK_net; -extern mysql_mutex_t THR_LOCK_charset, THR_LOCK_time; - -#include <mysql/psi/mysql_file.h> - -#ifdef HAVE_PSI_INTERFACE -#ifdef HUGETLB_USE_PROC_MEMINFO -extern PSI_file_key key_file_proc_meminfo; -#endif /* HUGETLB_USE_PROC_MEMINFO */ -extern PSI_file_key key_file_charset, key_file_cnf; -#endif /* HAVE_PSI_INTERFACE */ - -/* - EDQUOT is used only in 3 C files only in mysys/. If it does not exist on - system, we set it to some value which can never happen. -*/ -#ifndef EDQUOT -#define EDQUOT (-1) -#endif - -void my_error_unregister_all(void); - -#ifdef _WIN32 -#include <sys/stat.h> -/* my_winfile.c exports, should not be used outside mysys */ -extern File my_win_open(const char *path, int oflag); -extern int my_win_close(File fd); -extern size_t my_win_read(File fd, uchar *buffer, size_t count); -extern size_t my_win_write(File fd, const uchar *buffer, size_t count); -extern size_t my_win_pread(File fd, uchar *buffer, size_t count, - my_off_t offset); -extern size_t my_win_pwrite(File fd, const uchar *buffer, size_t count, - my_off_t offset); -extern my_off_t my_win_lseek(File fd, my_off_t pos, int whence); -extern int my_win_chsize(File fd, my_off_t newlength); -extern FILE* my_win_fopen(const char *filename, const char *type); -extern File my_win_fclose(FILE *file); -extern File my_win_fileno(FILE *file); -extern FILE* my_win_fdopen(File Filedes, const char *type); -extern int my_win_stat(const char *path, struct _stati64 *buf); -extern int my_win_fstat(File fd, struct _stati64 *buf); -extern int my_win_fsync(File fd); -extern File my_win_dup(File fd); -extern File my_win_sopen(const char *path, int oflag, int shflag, int perm); -extern File my_open_osfhandle(HANDLE handle, int oflag); -#endif diff --git a/dep/mysqllite/mysys/ptr_cmp.c b/dep/mysqllite/mysys/ptr_cmp.c deleted file mode 100644 index dcafe13291d..00000000000 --- a/dep/mysqllite/mysys/ptr_cmp.c +++ /dev/null @@ -1,223 +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 */ - -/* - get_ptr_compare(len) returns a pointer to a optimal byte-compare function - for a array of stringpointer where all strings have size len. - The bytes are compare as unsigned chars. - */ - -#include "mysys_priv.h" -#include <myisampack.h> - -#ifdef __sun -/* - * On Solaris, memcmp() is normally faster than the unrolled ptr_compare_N - * functions, as memcmp() is usually a platform-specific implementation - * written in assembler, provided in /usr/lib/libc/libc_hwcap*.so.1. - * This implementation is also usually faster than the built-in memcmp - * supplied by GCC, so it is recommended to build with "-fno-builtin-memcmp" - * in CFLAGS if building with GCC on Solaris. - */ - -#include <string.h> - -static int native_compare(size_t *length, unsigned char **a, unsigned char **b) -{ - return memcmp(*a, *b, *length); -} - -#else /* __sun */ - -static int ptr_compare(size_t *compare_length, uchar **a, uchar **b); -static int ptr_compare_0(size_t *compare_length, uchar **a, uchar **b); -static int ptr_compare_1(size_t *compare_length, uchar **a, uchar **b); -static int ptr_compare_2(size_t *compare_length, uchar **a, uchar **b); -static int ptr_compare_3(size_t *compare_length, uchar **a, uchar **b); -#endif /* __sun */ - - /* Get a pointer to a optimal byte-compare function for a given size */ - -#ifdef __sun -qsort2_cmp get_ptr_compare (size_t size __attribute__((unused))) -{ - return (qsort2_cmp) native_compare; -} -#else -qsort2_cmp get_ptr_compare (size_t size) -{ - if (size < 4) - return (qsort2_cmp) ptr_compare; - switch (size & 3) { - case 0: return (qsort2_cmp) ptr_compare_0; - case 1: return (qsort2_cmp) ptr_compare_1; - case 2: return (qsort2_cmp) ptr_compare_2; - case 3: return (qsort2_cmp) ptr_compare_3; - } - return 0; /* Impossible */ -} -#endif /* __sun */ - - - /* - Compare to keys to see witch is smaller. - Loop unrolled to make it quick !! - */ - -#define cmp(N) if (first[N] != last[N]) return (int) first[N] - (int) last[N] - -#ifndef __sun - -static int ptr_compare(size_t *compare_length, uchar **a, uchar **b) -{ - reg3 int length= *compare_length; - reg1 uchar *first,*last; - - first= *a; last= *b; - while (--length) - { - if (*first++ != *last++) - return (int) first[-1] - (int) last[-1]; - } - return (int) first[0] - (int) last[0]; -} - - -static int ptr_compare_0(size_t *compare_length,uchar **a, uchar **b) -{ - reg3 int length= *compare_length; - reg1 uchar *first,*last; - - first= *a; last= *b; - loop: - cmp(0); - cmp(1); - cmp(2); - cmp(3); - if ((length-=4)) - { - first+=4; - last+=4; - goto loop; - } - return (0); -} - - -static int ptr_compare_1(size_t *compare_length,uchar **a, uchar **b) -{ - reg3 int length= *compare_length-1; - reg1 uchar *first,*last; - - first= *a+1; last= *b+1; - cmp(-1); - loop: - cmp(0); - cmp(1); - cmp(2); - cmp(3); - if ((length-=4)) - { - first+=4; - last+=4; - goto loop; - } - return (0); -} - -static int ptr_compare_2(size_t *compare_length,uchar **a, uchar **b) -{ - reg3 int length= *compare_length-2; - reg1 uchar *first,*last; - - first= *a +2 ; last= *b +2; - cmp(-2); - cmp(-1); - loop: - cmp(0); - cmp(1); - cmp(2); - cmp(3); - if ((length-=4)) - { - first+=4; - last+=4; - goto loop; - } - return (0); -} - -static int ptr_compare_3(size_t *compare_length,uchar **a, uchar **b) -{ - reg3 int length= *compare_length-3; - reg1 uchar *first,*last; - - first= *a +3 ; last= *b +3; - cmp(-3); - cmp(-2); - cmp(-1); - loop: - cmp(0); - cmp(1); - cmp(2); - cmp(3); - if ((length-=4)) - { - first+=4; - last+=4; - goto loop; - } - return (0); -} - -#endif /* !__sun */ - -void my_store_ptr(uchar *buff, size_t pack_length, my_off_t pos) -{ - switch (pack_length) { -#if SIZEOF_OFF_T > 4 - case 8: mi_int8store(buff,pos); break; - case 7: mi_int7store(buff,pos); break; - case 6: mi_int6store(buff,pos); break; - case 5: mi_int5store(buff,pos); break; -#endif - case 4: mi_int4store(buff,pos); break; - case 3: mi_int3store(buff,pos); break; - case 2: mi_int2store(buff,pos); break; - case 1: buff[0]= (uchar) pos; break; - default: DBUG_ASSERT(0); - } - return; -} - -my_off_t my_get_ptr(uchar *ptr, size_t pack_length) -{ - my_off_t pos; - switch (pack_length) { -#if SIZEOF_OFF_T > 4 - case 8: pos= (my_off_t) mi_uint8korr(ptr); break; - case 7: pos= (my_off_t) mi_uint7korr(ptr); break; - case 6: pos= (my_off_t) mi_uint6korr(ptr); break; - case 5: pos= (my_off_t) mi_uint5korr(ptr); break; -#endif - 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) *(uchar*) ptr; break; - default: DBUG_ASSERT(0); return 0; - } - return pos; -} - diff --git a/dep/mysqllite/mysys/queues.c b/dep/mysqllite/mysys/queues.c deleted file mode 100644 index 25a310c0752..00000000000 --- a/dep/mysqllite/mysys/queues.c +++ /dev/null @@ -1,687 +0,0 @@ -/* 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 - 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 */ - -/* - 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" -#include "mysys_err.h" -#include <queues.h> - - -/* - Init queue - - SYNOPSIS - init_queue() - 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 - - NOTES - Will allocate max_element pointers for queue array - - RETURN - 0 ok - 1 Could not allocate memory -*/ - -int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key, - pbool max_at_top, int (*compare) (void *, uchar *, uchar *), - void *first_cmp_arg) -{ - DBUG_ENTER("init_queue"); - if ((queue->root= (uchar **) my_malloc((max_elements+1)*sizeof(void*), - MYF(MY_WME))) == 0) - DBUG_RETURN(1); - queue->elements=0; - queue->compare=compare; - queue->first_cmp_arg=first_cmp_arg; - queue->max_elements=max_elements; - queue->offset_to_key=offset_to_key; - queue_set_max_at_top(queue, max_at_top); - DBUG_RETURN(0); -} - - - -/* - 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 *, uchar *, uchar *), - 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 - - SYNOPSIS - reinit_queue() - 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 - - NOTES - This will delete all elements from the queue. If you don't want this, - use resize_queue() instead. - - RETURN - 0 ok - EE_OUTOFMEMORY Wrong max_elements -*/ - -int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key, - pbool max_at_top, int (*compare) (void *, uchar *, uchar *), - void *first_cmp_arg) -{ - DBUG_ENTER("reinit_queue"); - queue->elements=0; - queue->compare=compare; - queue->first_cmp_arg=first_cmp_arg; - queue->offset_to_key=offset_to_key; - queue_set_max_at_top(queue, max_at_top); - resize_queue(queue, max_elements); - DBUG_RETURN(0); -} - - -/* - Resize queue - - SYNOPSIS - resize_queue() - queue Queue - max_elements New max size for queue - - NOTES - If you resize queue to be less than the elements you have in it, - the extra elements will be deleted - - RETURN - 0 ok - 1 Error. In this case the queue is unchanged -*/ - -int resize_queue(QUEUE *queue, uint max_elements) -{ - uchar **new_root; - DBUG_ENTER("resize_queue"); - if (queue->max_elements == max_elements) - DBUG_RETURN(0); - if ((new_root= (uchar **) my_realloc((void *)queue->root, - (max_elements+1)*sizeof(void*), - MYF(MY_WME))) == 0) - DBUG_RETURN(1); - set_if_smaller(queue->elements, max_elements); - queue->max_elements= max_elements; - queue->root= new_root; - DBUG_RETURN(0); -} - - -/* - Delete queue - - SYNOPSIS - delete_queue() - queue Queue to delete - - IMPLEMENTATION - Just free allocated memory. - - NOTES - Can be called safely multiple times -*/ - -void delete_queue(QUEUE *queue) -{ - DBUG_ENTER("delete_queue"); - my_free(queue->root); - queue->root= NULL; - DBUG_VOID_RETURN; -} - - - /* Code for insert, search and delete of elements */ - -void queue_insert(register QUEUE *queue, uchar *element) -{ - reg2 uint idx, next; - DBUG_ASSERT(queue->elements < queue->max_elements); - queue->root[0]= element; - idx= ++queue->elements; - /* max_at_top swaps the comparison if we want to order by desc */ - while ((queue->compare(queue->first_cmp_arg, - element + queue->offset_to_key, - queue->root[(next= idx >> 1)] + - queue->offset_to_key) * queue->max_at_top) < 0) - { - queue->root[idx]= queue->root[next]; - idx= next; - } - 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, uchar *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 */ - -uchar *queue_remove(register QUEUE *queue, uint idx) -{ - uchar *element; - DBUG_ASSERT(idx < queue->max_elements); - element= queue->root[++idx]; /* Intern index starts from 1 */ - queue->root[idx]= queue->root[queue->elements--]; - _downheap(queue, idx); - return element; -} - - /* Fix when element on top has been replaced */ - -#ifndef queue_replaced -void queue_replaced(QUEUE *queue) -{ - _downheap(queue,1); -} -#endif - -#ifndef OLD_VERSION - -void _downheap(register QUEUE *queue, uint idx) -{ - uchar *element; - uint elements,half_queue,offset_to_key, next_index; - my_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) - { - 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 && - (((queue->compare(queue->first_cmp_arg, - queue->root[next_index]+offset_to_key, - element+offset_to_key) * 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) -{ - uchar *element; - uint elements,half_queue,next_index,offset_to_key; - - offset_to_key=queue->offset_to_key; - element=queue->root[idx]; - half_queue=(elements=queue->elements) >> 1; - - while (idx <= half_queue) - { - 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 ((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; - } - queue->root[idx]=element; -} - - -#endif - -/* - Fix heap when every element was changed. -*/ - -void queue_fix(QUEUE *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, uchar *a, uchar *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)= (uchar*)&num_array[i]; - else - queue_insert(queue, (uchar*)&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)= (uchar*)&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)= (uchar*)&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/dep/mysqllite/mysys/rijndael.c b/dep/mysqllite/mysys/rijndael.c deleted file mode 100644 index 2d622efad82..00000000000 --- a/dep/mysqllite/mysys/rijndael.c +++ /dev/null @@ -1,1379 +0,0 @@ -/* Copyright (C) 2002, 2004 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 */ - - -/* - Based on version 3.0 (December 2000) - - Optimised ANSI C code for the Rijndael cipher (now AES) - - author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> - author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> - author Paulo Barreto <paulo.barreto@terra.com.br> -*/ - -#include <my_global.h> -#include "rijndael.h" - -/* - Define the following to use fastest and much larger code (~10K extra code) - #define FULL_UNROLL -*/ - -static const uint32 Te0[256]= -{ - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; - -static const uint32 Te1[256]= -{ - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; - -static const uint32 Te2[256]= -{ - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; - -static const uint32 Te3[256]= -{ - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; - -static const uint32 Te4[256]= -{ - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; - -static const uint32 Td0[256]= -{ - 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, - 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, - 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, - 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, - 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, - 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, - 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, - 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, - 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, - 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, - 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, - 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, - 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, - 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, - 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, - 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, - 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, - 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, - 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, - 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, - 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, - 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, - 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, - 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, - 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, - 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, - 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, - 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, - 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, - 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, - 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, - 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, - 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, - 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, - 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, - 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, - 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, - 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, - 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, - 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, - 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, - 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, - 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, - 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, - 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, - 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, - 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, - 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, - 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, - 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, - 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, - 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, - 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, - 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, - 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, - 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, - 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, - 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, - 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, - 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, - 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, - 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, - 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, - 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, -}; - -static const uint32 Td1[256]= -{ - 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, - 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, - 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, - 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, - 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, - 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, - 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, - 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, - 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, - 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, - 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, - 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, - 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, - 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, - 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, - 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, - 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, - 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, - 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, - 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, - 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, - 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, - 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, - 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, - 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, - 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, - 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, - 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, - 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, - 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, - 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, - 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, - 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, - 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, - 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, - 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, - 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, - 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, - 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, - 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, - 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, - 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, - 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, - 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, - 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, - 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, - 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, - 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, - 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, - 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, - 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, - 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, - 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, - 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, - 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, - 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, - 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, - 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, - 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, - 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, - 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, - 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, - 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, - 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, -}; - -static const uint32 Td2[256]= -{ - 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, - 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, - 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, - 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, - 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, - 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, - 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, - 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, - 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, - 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, - 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, - 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, - 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, - 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, - 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, - 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, - 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, - 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, - 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, - 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, - - 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, - 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, - 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, - 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, - 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, - 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, - 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, - 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, - 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, - 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, - 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, - 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, - 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, - 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, - 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, - 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, - 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, - 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, - 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, - 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, - 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, - 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, - 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, - 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, - 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, - 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, - 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, - 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, - 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, - 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, - 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, - 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, - 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, - 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, - 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, - 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, - 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, - 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, - 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, - 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, - 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, - 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, - 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, - 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, -}; - -static const uint32 Td3[256]= -{ - 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, - 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, - 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, - 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, - 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, - 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, - 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, - 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, - 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, - 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, - 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, - 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, - 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, - 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, - 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, - 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, - 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, - 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, - 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, - 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, - 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, - 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, - 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, - 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, - 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, - 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, - 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, - 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, - 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, - 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, - 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, - 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, - 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, - 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, - 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, - 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, - 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, - 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, - 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, - 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, - 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, - 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, - 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, - 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, - 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, - 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, - 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, - 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, - 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, - 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, - 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, - 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, - 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, - 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, - 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, - 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, - 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, - 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, - 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, - 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, - 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, - 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, - 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, - 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, -}; - -static const uint32 Td4[256]= -{ - 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, - 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, - 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, - 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, - 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, - 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, - 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, - 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, - 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, - 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, - 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, - 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, - 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, - 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, - 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, - 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, - 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, - 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, - 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, - 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, - 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, - 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, - 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, - 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, - 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, - 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, - 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, - 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, - 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, - 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, - 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, - 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, - 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, - 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, - 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, - 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, - 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, - 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, - 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, - 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, - 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, - 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, - 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, - 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, - 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, - 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, - 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, - 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, - 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, - 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, - 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, - 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, - 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, - 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, - 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, - 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, - 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, - 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, - 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, - 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, - 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, - 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, - 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, - 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, -}; - - -/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -static const uint32 rcon[]= -{ - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, -}; - -#if defined(_MSC_VER) && defined(__i386__) - -#define RJ_SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) -#define GETuint32(p) RJ_SWAP(*((uint32 *)(p))) -#define PUTuint32(ct, st) { *((uint32 *)(ct)) = RJ_SWAP((st)); } - -#else - -#define GETuint32(pt) (((uint32)(pt)[0] << 24) ^ ((uint32)(pt)[1] << 16)\ - ^ ((uint32)(pt)[2] << 8) ^ ((uint32)(pt)[3])) -#define PUTuint32(ct, st) { (ct)[0] = (uint8)((st) >> 24); (ct)[1]\ -= (uint8)((st) >> 16); (ct)[2] = (uint8)((st) >> 8); (ct)[3] = (uint8)(st); } - -#endif /* defined(_MSC_VER) && defined(__i386__) */ - - -/* - Expand the cipher key into the encryption key schedule. - - RETURN - The number of rounds for the given cipher key size. -*/ - -int rijndaelKeySetupEnc(uint32 rk[/*4*(Nr + 1)*/], const uint8 cipherKey[], - int keyBits) -{ - int i = 0; - uint32 temp; - - rk[0] = GETuint32(cipherKey ); - rk[1] = GETuint32(cipherKey + 4); - rk[2] = GETuint32(cipherKey + 8); - rk[3] = GETuint32(cipherKey + 12); - if (keyBits == 128) - { - for (;;) - { - temp = rk[3]; - rk[4] = (rk[0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]); - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - if (++i == 10) - return 10; - rk += 4; - } - } - rk[4] = GETuint32(cipherKey + 16); - rk[5] = GETuint32(cipherKey + 20); - if (keyBits == 192) - { - for (;;) - { - temp = rk[ 5]; - rk[ 6] = (rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]); - rk[ 7] = rk[ 1] ^ rk[ 6]; - rk[ 8] = rk[ 2] ^ rk[ 7]; - rk[ 9] = rk[ 3] ^ rk[ 8]; - if (++i == 8) - { - return 12; - } - rk[10] = rk[ 4] ^ rk[ 9]; - rk[11] = rk[ 5] ^ rk[10]; - rk += 6; - } - } - rk[6] = GETuint32(cipherKey + 24); - rk[7] = GETuint32(cipherKey + 28); - if (keyBits == 256) - { - for (;;) - { - temp = rk[ 7]; - rk[ 8] = (rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]); - rk[ 9] = rk[ 1] ^ rk[ 8]; - rk[10] = rk[ 2] ^ rk[ 9]; - rk[11] = rk[ 3] ^ rk[10]; - if (++i == 7) - { - return 14; - } - temp = rk[11]; - rk[12] = (rk[ 4] ^ - (Te4[(temp >> 24) ] & 0xff000000) ^ - (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(temp ) & 0xff] & 0x000000ff)); - rk[13] = rk[ 5] ^ rk[12]; - rk[14] = rk[ 6] ^ rk[13]; - rk[15] = rk[ 7] ^ rk[14]; - rk += 8; - } - } - return 0; -} - - -/* - Expand the cipher key into the decryption key schedule. - - RETURN - The number of rounds for the given cipher key size. -*/ - -int rijndaelKeySetupDec(uint32 rk[/*4*(Nr + 1)*/], const uint8 cipherKey[], - int keyBits) -{ - int nr, i, j; - uint32 temp; - - /* expand the cipher key: */ - nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); - /* invert the order of the round keys: */ - for (i = 0, j = 4*nr; i < j; i += 4, j -= 4) - { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* - Apply the inverse MixColumn transform to all round keys but the first - and the last: - */ - for (i = 1; i < nr; i++) - { - rk += 4; - - rk[0]= ( - Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[0] ) & 0xff] & 0xff]); - - rk[1]= (Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[1] ) & 0xff] & 0xff]); - - rk[2]= (Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[2] ) & 0xff] & 0xff]); - - rk[3]= (Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ - Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ - Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ - Td3[Te4[(rk[3] ) & 0xff] & 0xff]); - } - return nr; -} - - -void rijndaelEncrypt(const uint32 rk[/*4*(Nr + 1)*/], int Nr, - const uint8 pt[16], uint8 ct[16]) -{ - uint32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* FULL_UNROLL */ - - /* map byte array block to cipher state and add initial round key: */ - s0 = GETuint32(pt ) ^ rk[0]; - s1 = GETuint32(pt + 4) ^ rk[1]; - s2 = GETuint32(pt + 8) ^ rk[2]; - s3 = GETuint32(pt + 12) ^ rk[3]; - -#ifdef FULL_UNROLL - /* round 1: */ - t0= (Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] - ^ Te3[s3 & 0xff] ^ rk[ 4]); - t1= (Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] - ^ Te3[s0 & 0xff] ^ rk[ 5]); - t2= (Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] - ^ Te3[s1 & 0xff] ^ rk[ 6]); - t3= (Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] - ^ Te3[s2 & 0xff] ^ rk[ 7]); - - /* round 2: */ - s0= (Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] - ^ Te3[t3 & 0xff] ^ rk[ 8]); - s1= (Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] - ^ Te3[t0 & 0xff] ^ rk[ 9]); - s2= (Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] - ^ Te3[t1 & 0xff] ^ rk[10]); - s3= (Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] - ^ Te3[t2 & 0xff] ^ rk[11]); - - /* round 3: */ - t0= (Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] - ^ Te3[s3 & 0xff] ^ rk[12]); - t1= (Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] - ^ Te3[s0 & 0xff] ^ rk[13]); - t2= (Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] - ^ Te3[s1 & 0xff] ^ rk[14]); - t3= (Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] - ^ Te3[s2 & 0xff] ^ rk[15]); - - /* round 4: */ - s0= (Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] - ^ Te3[t3 & 0xff] ^ rk[16]); - s1= (Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] - ^ Te3[t0 & 0xff] ^ rk[17]); - s2= (Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] - ^ Te3[t1 & 0xff] ^ rk[18]); - s3= (Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] - ^ Te3[t2 & 0xff] ^ rk[19]); - - /* round 5: */ - t0= (Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] - ^ Te3[s3 & 0xff] ^ rk[20]); - t1= (Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] - ^ Te3[s0 & 0xff] ^ rk[21]); - t2= (Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] - ^ Te3[s1 & 0xff] ^ rk[22]); - t3= (Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] - ^ Te3[s2 & 0xff] ^ rk[23]); - - /* round 6: */ - s0= (Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] - ^ Te3[t3 & 0xff] ^ rk[24]); - s1= (Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] - ^ Te3[t0 & 0xff] ^ rk[25]); - s2= (Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] - ^ Te3[t1 & 0xff] ^ rk[26]); - s3= (Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] - ^ Te3[t2 & 0xff] ^ rk[27]); - - /* round 7: */ - t0= (Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] - ^ Te3[s3 & 0xff] ^ rk[28]); - t1= (Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] - ^ Te3[s0 & 0xff] ^ rk[29]); - t2= (Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] - ^ Te3[s1 & 0xff] ^ rk[30]); - t3= (Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] - ^ Te3[s2 & 0xff] ^ rk[31]); - - /* round 8: */ - s0= (Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] - ^ Te3[t3 & 0xff] ^ rk[32]); - s1= (Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] - ^ Te3[t0 & 0xff] ^ rk[33]); - s2= (Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] - ^ Te3[t1 & 0xff] ^ rk[34]); - s3= (Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] - ^ Te3[t2 & 0xff] ^ rk[35]); - - /* round 9: */ - t0= (Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] - ^ Te3[s3 & 0xff] ^ rk[36]); - t1= (Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] - ^ Te3[s0 & 0xff] ^ rk[37]); - t2= (Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] - ^ Te3[s1 & 0xff] ^ rk[38]); - t3= (Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] - ^ Te3[s2 & 0xff] ^ rk[39]); - - if (Nr > 10) - { - /* round 10: */ - s0= (Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] - ^ Te3[t3 & 0xff] ^ rk[40]); - s1= (Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] - ^ Te3[t0 & 0xff] ^ rk[41]); - s2= (Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] - ^ Te3[t1 & 0xff] ^ rk[42]); - s3= (Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] - ^ Te3[t2 & 0xff] ^ rk[43]); - - /* round 11: */ - t0= (Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] - ^ Te3[s3 & 0xff] ^ rk[44]); - t1= (Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] - ^ Te3[s0 & 0xff] ^ rk[45]); - t2= (Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] - ^ Te3[s1 & 0xff] ^ rk[46]); - t3= (Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] - ^ Te3[s2 & 0xff] ^ rk[47]); - - if (Nr > 12) - { - /* round 12: */ - s0= (Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] - ^ Te3[t3 & 0xff] ^ rk[48]); - s1= (Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] - ^ Te3[t0 & 0xff] ^ rk[49]); - s2= (Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] - ^ Te3[t1 & 0xff] ^ rk[50]); - s3= (Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] - ^ Te3[t2 & 0xff] ^ rk[51]); - - /* round 13: */ - t0= (Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] - ^ Te3[s3 & 0xff] ^ rk[52]); - t1= (Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] - ^ Te3[s0 & 0xff] ^ rk[53]); - t2= (Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] - ^ Te3[s1 & 0xff] ^ rk[54]); - t3= (Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] - ^ Te3[s2 & 0xff] ^ rk[55]); - } - } - rk += Nr << 2; -#else /* !FULL_UNROLL */ - - /* Nr - 1 full rounds: */ - - r = Nr >> 1; - for (;;) - { - t0= (Te0[(s0 >> 24) ] ^ - Te1[(s1 >> 16) & 0xff] ^ - Te2[(s2 >> 8) & 0xff] ^ - Te3[(s3 ) & 0xff] ^ - rk[4]); - - t1= (Te0[(s1 >> 24) ] ^ - Te1[(s2 >> 16) & 0xff] ^ - Te2[(s3 >> 8) & 0xff] ^ - Te3[(s0 ) & 0xff] ^ - rk[5]); - - t2= (Te0[(s2 >> 24) ] ^ - Te1[(s3 >> 16) & 0xff] ^ - Te2[(s0 >> 8) & 0xff] ^ - Te3[(s1 ) & 0xff] ^ - rk[6]); - - t3= (Te0[(s3 >> 24) ] ^ - Te1[(s0 >> 16) & 0xff] ^ - Te2[(s1 >> 8) & 0xff] ^ - Te3[(s2 ) & 0xff] ^ - rk[7]); - - rk+= 8; - if (--r == 0) - break; - - s0= (Te0[(t0 >> 24) ] ^ - Te1[(t1 >> 16) & 0xff] ^ - Te2[(t2 >> 8) & 0xff] ^ - Te3[(t3 ) & 0xff] ^ - rk[0]); - - s1= (Te0[(t1 >> 24) ] ^ - Te1[(t2 >> 16) & 0xff] ^ - Te2[(t3 >> 8) & 0xff] ^ - Te3[(t0 ) & 0xff] ^ - rk[1]); - - s2= (Te0[(t2 >> 24) ] ^ - Te1[(t3 >> 16) & 0xff] ^ - Te2[(t0 >> 8) & 0xff] ^ - Te3[(t1 ) & 0xff] ^ - rk[2]); - - s3= (Te0[(t3 >> 24) ] ^ - Te1[(t0 >> 16) & 0xff] ^ - Te2[(t1 >> 8) & 0xff] ^ - Te3[(t2 ) & 0xff] ^ - rk[3]); - } -#endif /* FULL_UNROLL */ - - /* Apply last round and map cipher state to byte array block: */ - s0= ((Te4[(t0 >> 24) ] & 0xff000000) ^ - (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[0]); - PUTuint32(ct , s0); - - s1= ((Te4[(t1 >> 24) ] & 0xff000000) ^ - (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[1]); - PUTuint32(ct + 4, s1); - - s2= ((Te4[(t2 >> 24) ] & 0xff000000) ^ - (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[2]); - PUTuint32(ct + 8, s2); - - s3= ((Te4[(t3 >> 24) ] & 0xff000000) ^ - (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[3]); - PUTuint32(ct + 12, s3); -} - - -void rijndaelDecrypt(const uint32 rk[/*4*(Nr + 1)*/], int Nr, - const uint8 ct[16], uint8 pt[16]) -{ - uint32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* FULL_UNROLL */ - - /* Map byte array block to cipher state and add initial round key: */ - - s0 = GETuint32(ct ) ^ rk[0]; - s1 = GETuint32(ct + 4) ^ rk[1]; - s2 = GETuint32(ct + 8) ^ rk[2]; - s3 = GETuint32(ct + 12) ^ rk[3]; - -#ifdef FULL_UNROLL - /* round 1: */ - t0= (Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] - ^ Td3[s1 & 0xff] ^ rk[ 4]); - t1= (Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] - ^ Td3[s2 & 0xff] ^ rk[ 5]); - t2= (Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] - ^ Td3[s3 & 0xff] ^ rk[ 6]); - t3= (Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] - ^ Td3[s0 & 0xff] ^ rk[ 7]); - - /* round 2: */ - s0= (Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] - ^ Td3[t1 & 0xff] ^ rk[ 8]); - s1= (Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] - ^ Td3[t2 & 0xff] ^ rk[ 9]); - s2= (Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] - ^ Td3[t3 & 0xff] ^ rk[10]); - s3= (Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] - ^ Td3[t0 & 0xff] ^ rk[11]); - - /* round 3: */ - t0= (Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] - ^ Td3[s1 & 0xff] ^ rk[12]); - t1= (Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] - ^ Td3[s2 & 0xff] ^ rk[13]); - t2= (Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] - ^ Td3[s3 & 0xff] ^ rk[14]); - t3= (Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] - ^ Td3[s0 & 0xff] ^ rk[15]); - - /* round 4: */ - s0= (Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] - ^ Td3[t1 & 0xff] ^ rk[16]); - s1= (Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] - ^ Td3[t2 & 0xff] ^ rk[17]); - s2= (Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] - ^ Td3[t3 & 0xff] ^ rk[18]); - s3= (Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] - ^ Td3[t0 & 0xff] ^ rk[19]); - - /* round 5: */ - t0= (Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] - ^ Td3[s1 & 0xff] ^ rk[20]); - t1= (Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] - ^ Td3[s2 & 0xff] ^ rk[21]); - t2= (Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] - ^ Td3[s3 & 0xff] ^ rk[22]); - t3= (Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] - ^ Td3[s0 & 0xff] ^ rk[23]); - - /* round 6: */ - s0= (Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] - ^ Td3[t1 & 0xff] ^ rk[24]); - s1= (Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] - ^ Td3[t2 & 0xff] ^ rk[25]); - s2= (Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] - ^ Td3[t3 & 0xff] ^ rk[26]); - s3= (Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] - ^ Td3[t0 & 0xff] ^ rk[27]); - - /* round 7: */ - t0= (Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] - ^ Td3[s1 & 0xff] ^ rk[28]); - t1= (Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] - ^ Td3[s2 & 0xff] ^ rk[29]); - t2= (Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] - ^ Td3[s3 & 0xff] ^ rk[30]); - t3= (Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] - ^ Td3[s0 & 0xff] ^ rk[31]); - - /* round 8: */ - s0= (Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] - ^ Td3[t1 & 0xff] ^ rk[32]); - s1= (Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] - ^ Td3[t2 & 0xff] ^ rk[33]); - s2= (Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] - ^ Td3[t3 & 0xff] ^ rk[34]); - s3= (Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] - ^ Td3[t0 & 0xff] ^ rk[35]); - - /* round 9: */ - t0= (Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] - ^ Td3[s1 & 0xff] ^ rk[36]); - t1= (Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] - ^ Td3[s2 & 0xff] ^ rk[37]); - t2= (Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] - ^ Td3[s3 & 0xff] ^ rk[38]); - t3= (Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] - ^ Td3[s0 & 0xff] ^ rk[39]); - - if (Nr > 10) - { - /* round 10: */ - s0= (Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] - ^ Td3[t1 & 0xff] ^ rk[40]); - s1= (Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] - ^ Td3[t2 & 0xff] ^ rk[41]); - s2= (Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] - ^ Td3[t3 & 0xff] ^ rk[42]); - s3= (Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] - ^ Td3[t0 & 0xff] ^ rk[43]); - - /* round 11: */ - t0= (Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] - ^ Td3[s1 & 0xff] ^ rk[44]); - t1= (Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] - ^ Td3[s2 & 0xff] ^ rk[45]); - t2= (Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] - ^ Td3[s3 & 0xff] ^ rk[46]); - t3= (Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] - ^ Td3[s0 & 0xff] ^ rk[47]); - - if (Nr > 12) - { - /* round 12: */ - s0= (Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] - ^ Td3[t1 & 0xff] ^ rk[48]); - s1= (Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] - ^ Td3[t2 & 0xff] ^ rk[49]); - s2= (Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] - ^ Td3[t3 & 0xff] ^ rk[50]); - s3= (Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] - ^ Td3[t0 & 0xff] ^ rk[51]); - - /* round 13: */ - t0= (Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] - ^ Td3[s1 & 0xff] ^ rk[52]); - t1= (Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] - ^ Td3[s2 & 0xff] ^ rk[53]); - t2= (Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] - ^ Td3[s3 & 0xff] ^ rk[54]); - t3= (Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] - ^ Td3[s0 & 0xff] ^ rk[55]); - } - } - rk += Nr << 2; -#else /* !FULL_UNROLL */ - - /* Nr - 1 full rounds: */ - r= (Nr >> 1); - for (;;) - { - t0= (Td0[(s0 >> 24) ] ^ - Td1[(s3 >> 16) & 0xff] ^ - Td2[(s2 >> 8) & 0xff] ^ - Td3[(s1 ) & 0xff] ^ - rk[4]); - - t1= (Td0[(s1 >> 24) ] ^ - Td1[(s0 >> 16) & 0xff] ^ - Td2[(s3 >> 8) & 0xff] ^ - Td3[(s2 ) & 0xff] ^ - rk[5]); - - t2= (Td0[(s2 >> 24) ] ^ - Td1[(s1 >> 16) & 0xff] ^ - Td2[(s0 >> 8) & 0xff] ^ - Td3[(s3 ) & 0xff] ^ - rk[6]); - - t3= (Td0[(s3 >> 24) ] ^ - Td1[(s2 >> 16) & 0xff] ^ - Td2[(s1 >> 8) & 0xff] ^ - Td3[(s0 ) & 0xff] ^ - rk[7]); - - rk+= 8; - if (--r == 0) - break; - - s0= (Td0[(t0 >> 24) ] ^ - Td1[(t3 >> 16) & 0xff] ^ - Td2[(t2 >> 8) & 0xff] ^ - Td3[(t1 ) & 0xff] ^ - rk[0]); - - s1= (Td0[(t1 >> 24) ] ^ - Td1[(t0 >> 16) & 0xff] ^ - Td2[(t3 >> 8) & 0xff] ^ - Td3[(t2 ) & 0xff] ^ - rk[1]); - - s2= (Td0[(t2 >> 24) ] ^ - Td1[(t1 >> 16) & 0xff] ^ - Td2[(t0 >> 8) & 0xff] ^ - Td3[(t3 ) & 0xff] ^ - rk[2]); - - s3= (Td0[(t3 >> 24) ] ^ - Td1[(t2 >> 16) & 0xff] ^ - Td2[(t1 >> 8) & 0xff] ^ - Td3[(t0 ) & 0xff] ^ - rk[3]); - } - -#endif /* FULL_UNROLL */ - - /* Apply last round and map cipher state to byte array block: */ - - s0= ((Td4[(t0 >> 24) ] & 0xff000000) ^ - (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[0]); - PUTuint32(pt , s0); - - s1= ((Td4[(t1 >> 24) ] & 0xff000000) ^ - (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[1]); - PUTuint32(pt + 4, s1); - - s2= ((Td4[(t2 >> 24) ] & 0xff000000) ^ - (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[2]); - PUTuint32(pt + 8, s2); - - s3= ((Td4[(t3 >> 24) ] & 0xff000000) ^ - (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Td4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[3]); - PUTuint32(pt + 12, s3); -} diff --git a/dep/mysqllite/mysys/sha1.c b/dep/mysqllite/mysys/sha1.c deleted file mode 100644 index e5b33a9ad13..00000000000 --- a/dep/mysqllite/mysys/sha1.c +++ /dev/null @@ -1,422 +0,0 @@ -/* Copyright (c) 2002, 2004, 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 Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - Original Source from: http://www.faqs.org/rfcs/rfc3174.html - - Copyright (C) The Internet Society (2001). All Rights Reserved. - - This document and translations of it may be copied and furnished to - others, and derivative works that comment on or otherwise explain it - or assist in its implementation may be prepared, copied, published - and distributed, in whole or in part, without restriction of any - kind, provided that the above copyright notice and this paragraph are - included on all such copies and derivative works. However, this - document itself may not be modified in any way, such as by removing - the copyright notice or references to the Internet Society or other - Internet organizations, except as needed for the purpose of - developing Internet standards in which case the procedures for - copyrights defined in the Internet Standards process must be - followed, or as required to translate it into languages other than - English. - - The limited permissions granted above are perpetual and will not be - revoked by the Internet Society or its successors or assigns. - - This document and the information contained herein is provided on an - "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING - TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING - BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION - HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - - Acknowledgement - Funding for the RFC Editor function is currently provided by the - Internet Society. - - DESCRIPTION - This file implements the Secure Hashing Algorithm 1 as - defined in FIPS PUB 180-1 published April 17, 1995. - - The SHA-1, produces a 160-bit message digest for a given data - stream. It should take about 2**n steps to find a message with the - same digest as a given message and 2**(n/2) to find any two - messages with the same digest, when n is the digest size in bits. - Therefore, this algorithm can serve as a means of providing a - "fingerprint" for a message. - - PORTABILITY ISSUES - SHA-1 is defined in terms of 32-bit "words". This code uses - <stdint.h> (included via "sha1.h" to define 32 and 8 bit unsigned - integer types. If your C compiler does not support 32 bit unsigned - integers, this code is not appropriate. - - CAVEATS - SHA-1 is designed to work with messages less than 2^64 bits long. - Although SHA-1 allows a message digest to be generated for messages - of any number of bits less than 2^64, this implementation only - works with messages with a length that is a multiple of the size of - an 8-bit character. - - CHANGES - 2002 by Peter Zaitsev to - - fit to new prototypes according to MySQL standard - - Some optimizations - - All checking is now done in debug only mode - - More comments -*/ - -#include "my_global.h" -#include "m_string.h" -#include "sha1.h" - -/* - Define the SHA1 circular left shift macro -*/ - -#define SHA1CircularShift(bits,word) \ - (((word) << (bits)) | ((word) >> (32-(bits)))) - -/* Local Function Prototyptes */ -static void SHA1PadMessage(SHA1_CONTEXT*); -static void SHA1ProcessMessageBlock(SHA1_CONTEXT*); - - -/* - Initialize SHA1Context - - SYNOPSIS - mysql_sha1_reset() - context [in/out] The context to reset. - - DESCRIPTION - This function will initialize the SHA1Context in preparation - for computing a new SHA1 message digest. - - RETURN - SHA_SUCCESS ok - != SHA_SUCCESS sha Error Code. -*/ - - -const uint32 sha_const_key[5]= -{ - 0x67452301, - 0xEFCDAB89, - 0x98BADCFE, - 0x10325476, - 0xC3D2E1F0 -}; - - -int mysql_sha1_reset(SHA1_CONTEXT *context) -{ -#ifndef DBUG_OFF - if (!context) - return SHA_NULL; -#endif - - context->Length = 0; - context->Message_Block_Index = 0; - - context->Intermediate_Hash[0] = sha_const_key[0]; - context->Intermediate_Hash[1] = sha_const_key[1]; - context->Intermediate_Hash[2] = sha_const_key[2]; - context->Intermediate_Hash[3] = sha_const_key[3]; - context->Intermediate_Hash[4] = sha_const_key[4]; - - context->Computed = 0; - context->Corrupted = 0; - - return SHA_SUCCESS; -} - - -/* - Return the 160-bit message digest into the array provided by the caller - - SYNOPSIS - mysql_sha1_result() - context [in/out] The context to use to calculate the SHA-1 hash. - Message_Digest: [out] Where the digest is returned. - - DESCRIPTION - NOTE: The first octet of hash is stored in the 0th element, - the last octet of hash in the 19th element. - - RETURN - SHA_SUCCESS ok - != SHA_SUCCESS sha Error Code. -*/ - -int mysql_sha1_result(SHA1_CONTEXT *context, - uint8 Message_Digest[SHA1_HASH_SIZE]) -{ - int i; - -#ifndef DBUG_OFF - if (!context || !Message_Digest) - return SHA_NULL; - - if (context->Corrupted) - return context->Corrupted; -#endif - - if (!context->Computed) - { - SHA1PadMessage(context); - /* message may be sensitive, clear it out */ - bzero((char*) context->Message_Block,64); - context->Length = 0; /* and clear length */ - context->Computed = 1; - } - - for (i = 0; i < SHA1_HASH_SIZE; i++) - Message_Digest[i] = (int8)((context->Intermediate_Hash[i>>2] >> 8 - * ( 3 - ( i & 0x03 ) ))); - return SHA_SUCCESS; -} - - -/* - Accepts an array of octets as the next portion of the message. - - SYNOPSIS - mysql_sha1_input() - context [in/out] The SHA context to update - message_array An array of characters representing the next portion - of the message. - length The length of the message in message_array - - RETURN - SHA_SUCCESS ok - != SHA_SUCCESS sha Error Code. -*/ - -int mysql_sha1_input(SHA1_CONTEXT *context, const uint8 *message_array, - unsigned length) -{ - if (!length) - return SHA_SUCCESS; - -#ifndef DBUG_OFF - /* We assume client konows what it is doing in non-debug mode */ - if (!context || !message_array) - return SHA_NULL; - if (context->Computed) - return (context->Corrupted= SHA_STATE_ERROR); - if (context->Corrupted) - return context->Corrupted; -#endif - - while (length--) - { - context->Message_Block[context->Message_Block_Index++]= - (*message_array & 0xFF); - context->Length += 8; /* Length is in bits */ - -#ifndef DBUG_OFF - /* - Then we're not debugging we assume we never will get message longer - 2^64 bits. - */ - if (context->Length == 0) - return (context->Corrupted= 1); /* Message is too long */ -#endif - - if (context->Message_Block_Index == 64) - { - SHA1ProcessMessageBlock(context); - } - message_array++; - } - return SHA_SUCCESS; -} - - -/* - Process the next 512 bits of the message stored in the Message_Block array. - - SYNOPSIS - SHA1ProcessMessageBlock() - - DESCRIPTION - Many of the variable names in this code, especially the single - character names, were used because those were the names used in - the publication. -*/ - -/* Constants defined in SHA-1 */ -static const uint32 K[]= -{ - 0x5A827999, - 0x6ED9EBA1, - 0x8F1BBCDC, - 0xCA62C1D6 -}; - - -static void SHA1ProcessMessageBlock(SHA1_CONTEXT *context) -{ - int t; /* Loop counter */ - uint32 temp; /* Temporary word value */ - uint32 W[80]; /* Word sequence */ - uint32 A, B, C, D, E; /* Word buffers */ - int idx; - - /* - Initialize the first 16 words in the array W - */ - - for (t = 0; t < 16; t++) - { - idx=t*4; - W[t] = context->Message_Block[idx] << 24; - W[t] |= context->Message_Block[idx + 1] << 16; - W[t] |= context->Message_Block[idx + 2] << 8; - W[t] |= context->Message_Block[idx + 3]; - } - - - for (t = 16; t < 80; t++) - { - W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); - } - - A = context->Intermediate_Hash[0]; - B = context->Intermediate_Hash[1]; - C = context->Intermediate_Hash[2]; - D = context->Intermediate_Hash[3]; - E = context->Intermediate_Hash[4]; - - for (t = 0; t < 20; t++) - { - temp= SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for (t = 20; t < 40; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for (t = 40; t < 60; t++) - { - temp= (SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + - K[2]); - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - for (t = 60; t < 80; t++) - { - temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; - E = D; - D = C; - C = SHA1CircularShift(30,B); - B = A; - A = temp; - } - - context->Intermediate_Hash[0] += A; - context->Intermediate_Hash[1] += B; - context->Intermediate_Hash[2] += C; - context->Intermediate_Hash[3] += D; - context->Intermediate_Hash[4] += E; - - context->Message_Block_Index = 0; -} - - -/* - Pad message - - SYNOPSIS - SHA1PadMessage() - context: [in/out] The context to pad - - DESCRIPTION - According to the standard, the message must be padded to an even - 512 bits. The first padding bit must be a '1'. The last 64 bits - represent the length of the original message. All bits in between - should be 0. This function will pad the message according to - those rules by filling the Message_Block array accordingly. It - will also call the ProcessMessageBlock function provided - appropriately. When it returns, it can be assumed that the message - digest has been computed. - -*/ - -static void SHA1PadMessage(SHA1_CONTEXT *context) -{ - /* - Check to see if the current message block is too small to hold - the initial padding bits and length. If so, we will pad the - block, process it, and then continue padding into a second - block. - */ - - int i=context->Message_Block_Index; - - if (i > 55) - { - context->Message_Block[i++] = 0x80; - bzero((char*) &context->Message_Block[i], - sizeof(context->Message_Block[0])*(64-i)); - context->Message_Block_Index=64; - - /* This function sets context->Message_Block_Index to zero */ - SHA1ProcessMessageBlock(context); - - bzero((char*) &context->Message_Block[0], - sizeof(context->Message_Block[0])*56); - context->Message_Block_Index=56; - } - else - { - context->Message_Block[i++] = 0x80; - bzero((char*) &context->Message_Block[i], - sizeof(context->Message_Block[0])*(56-i)); - context->Message_Block_Index=56; - } - - /* - Store the message length as the last 8 octets - */ - - context->Message_Block[56] = (int8) (context->Length >> 56); - context->Message_Block[57] = (int8) (context->Length >> 48); - context->Message_Block[58] = (int8) (context->Length >> 40); - context->Message_Block[59] = (int8) (context->Length >> 32); - context->Message_Block[60] = (int8) (context->Length >> 24); - context->Message_Block[61] = (int8) (context->Length >> 16); - context->Message_Block[62] = (int8) (context->Length >> 8); - context->Message_Block[63] = (int8) (context->Length); - - SHA1ProcessMessageBlock(context); -} diff --git a/dep/mysqllite/mysys/stacktrace.c b/dep/mysqllite/mysys/stacktrace.c deleted file mode 100644 index 48cdaaa6c91..00000000000 --- a/dep/mysqllite/mysys/stacktrace.c +++ /dev/null @@ -1,714 +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 <my_global.h> -#include <my_stacktrace.h> - -#ifndef __WIN__ -#include <signal.h> -#include <my_pthread.h> -#include <m_string.h> -#ifdef HAVE_STACKTRACE -#include <unistd.h> -#include <strings.h> - -#ifdef __linux__ -#include <ctype.h> /* isprint */ -#include <sys/syscall.h> /* SYS_gettid */ -#endif - -#if HAVE_EXECINFO_H -#include <execinfo.h> -#endif - -#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) - -static char *heap_start; - -#ifdef HAVE_BSS_START -extern char *__bss_start; -#endif - -void my_init_stacktrace() -{ -#ifdef HAVE_BSS_START - heap_start = (char*) &__bss_start; -#endif -} - -#ifdef __linux__ - -static void print_buffer(char *buffer, size_t count) -{ - for (; count && *buffer; --count) - { - int c= (int) *buffer++; - fputc(isprint(c) ? c : ' ', stderr); - } -} - -/** - Access the pages of this process through /proc/self/task/<tid>/mem - in order to safely print the contents of a memory address range. - - @param addr The address at the start of the memory region. - @param max_len The length of the memory region. - - @return Zero on success. -*/ -static int safe_print_str(const char *addr, int max_len) -{ - int fd; - pid_t tid; - off_t offset; - ssize_t nbytes= 0; - size_t total, count; - char buf[256]; - - tid= (pid_t) syscall(SYS_gettid); - - sprintf(buf, "/proc/self/task/%d/mem", tid); - - if ((fd= open(buf, O_RDONLY)) < 0) - return -1; - - /* Ensure that off_t can hold a pointer. */ - compile_time_assert(sizeof(off_t) >= sizeof(intptr)); - - total= max_len; - offset= (intptr) addr; - - /* Read up to the maximum number of bytes. */ - while (total) - { - count= min(sizeof(buf), total); - - if ((nbytes= pread(fd, buf, count, offset)) < 0) - { - /* Just in case... */ - if (errno == EINTR) - continue; - else - break; - } - - /* Advance offset into memory. */ - total-= nbytes; - offset+= nbytes; - addr+= nbytes; - - /* Output the printable characters. */ - print_buffer(buf, nbytes); - - /* Break if less than requested... */ - if ((count - nbytes)) - break; - } - - /* Output a new line if something was printed. */ - if (total != (size_t) max_len) - fputc('\n', stderr); - - if (nbytes == -1) - fprintf(stderr, "Can't read from address %p: %m.\n", addr); - - close(fd); - - return 0; -} - -#endif - -void my_safe_print_str(const char* val, int max_len) -{ - char *heap_end; - -#ifdef __linux__ - if (!safe_print_str(val, max_len)) - return; -#endif - - heap_end= (char*) sbrk(0); - - if (!PTR_SANE(val)) - { - fprintf(stderr, "is an invalid pointer\n"); - return; - } - - for (; max_len && PTR_SANE(val) && *val; --max_len) - fputc(*val++, stderr); - fputc('\n', stderr); -} - -#if defined(HAVE_PRINTSTACK) - -/* Use Solaris' symbolic stack trace routine. */ -#include <ucontext.h> - -void my_print_stacktrace(uchar* stack_bottom __attribute__((unused)), - ulong thread_stack __attribute__((unused))) -{ - if (printstack(fileno(stderr)) == -1) - fprintf(stderr, "Error when traversing the stack, stack appears corrupt.\n"); - else - fprintf(stderr, - "Please read " - "http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n" - "and follow instructions on how to resolve the stack trace.\n" - "Resolved stack trace is much more helpful in diagnosing the\n" - "problem, so please do resolve it\n"); -} - -#elif HAVE_BACKTRACE && (HAVE_BACKTRACE_SYMBOLS || HAVE_BACKTRACE_SYMBOLS_FD) - -#if BACKTRACE_DEMANGLE - -char __attribute__ ((weak)) * -my_demangle(const char *mangled_name __attribute__((unused)), - int *status __attribute__((unused))) -{ - return NULL; -} - -static void my_demangle_symbols(char **addrs, int n) -{ - int status, i; - char *begin, *end, *demangled; - - for (i= 0; i < n; i++) - { - demangled= NULL; - begin= strchr(addrs[i], '('); - end= begin ? strchr(begin, '+') : NULL; - - if (begin && end) - { - *begin++= *end++= '\0'; - demangled= my_demangle(begin, &status); - if (!demangled || status) - { - demangled= NULL; - begin[-1]= '('; - end[-1]= '+'; - } - } - - if (demangled) - fprintf(stderr, "%s(%s+%s\n", addrs[i], demangled, end); - else - fprintf(stderr, "%s\n", addrs[i]); - } -} - -#endif /* BACKTRACE_DEMANGLE */ - -void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack) -{ - void *addrs[128]; - char **strings= NULL; - int n = backtrace(addrs, array_elements(addrs)); - fprintf(stderr, "stack_bottom = %p thread_stack 0x%lx\n", - stack_bottom, thread_stack); -#if BACKTRACE_DEMANGLE - if ((strings= backtrace_symbols(addrs, n))) - { - my_demangle_symbols(strings, n); - free(strings); - } -#endif -#if HAVE_BACKTRACE_SYMBOLS_FD - if (!strings) - { - backtrace_symbols_fd(addrs, n, fileno(stderr)); - } -#endif -} - -#elif defined(TARGET_OS_LINUX) - -#ifdef __i386__ -#define SIGRETURN_FRAME_OFFSET 17 -#endif - -#ifdef __x86_64__ -#define SIGRETURN_FRAME_OFFSET 23 -#endif - -#if defined(__alpha__) && defined(__GNUC__) -/* - The only way to backtrace without a symbol table on alpha - is to find stq fp,N(sp), and the first byte - of the instruction opcode will give us the value of N. From this - we can find where the old value of fp is stored -*/ - -#define MAX_INSTR_IN_FUNC 10000 - -inline uchar** find_prev_fp(uint32* pc, uchar** fp) -{ - int i; - for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc) - { - uchar* p = (uchar*)pc; - if (p[2] == 222 && p[3] == 35) - { - return (uchar**)((uchar*)fp - *(short int*)p); - } - } - return 0; -} - -inline uint32* find_prev_pc(uint32* pc, uchar** fp) -{ - int i; - for (i = 0; i < MAX_INSTR_IN_FUNC; ++i,--pc) - { - char* p = (char*)pc; - if (p[1] == 0 && p[2] == 94 && p[3] == -73) - { - uint32* prev_pc = (uint32*)*((fp+p[0]/sizeof(fp))); - return prev_pc; - } - } - return 0; -} -#endif /* defined(__alpha__) && defined(__GNUC__) */ - -void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack) -{ - uchar** fp; - uint frame_count = 0, sigreturn_frame_count; -#if defined(__alpha__) && defined(__GNUC__) - uint32* pc; -#endif - LINT_INIT(fp); - - -#ifdef __i386__ - __asm __volatile__ ("movl %%ebp,%0" - :"=r"(fp) - :"r"(fp)); -#endif -#ifdef __x86_64__ - __asm __volatile__ ("movq %%rbp,%0" - :"=r"(fp) - :"r"(fp)); -#endif -#if defined(__alpha__) && defined(__GNUC__) - __asm __volatile__ ("mov $30,%0" - :"=r"(fp) - :"r"(fp)); -#endif - if (!fp) - { - fprintf(stderr, "frame pointer is NULL, did you compile with\n\ --fomit-frame-pointer? Aborting backtrace!\n"); - return; - } - - if (!stack_bottom || (uchar*) stack_bottom > (uchar*) &fp) - { - ulong tmp= min(0x10000,thread_stack); - /* Assume that the stack starts at the previous even 65K */ - stack_bottom= (uchar*) (((ulong) &fp + tmp) & - ~(ulong) 0xFFFF); - fprintf(stderr, "Cannot determine thread, fp=%p, backtrace may not be correct.\n", fp); - } - if (fp > (uchar**) stack_bottom || - fp < (uchar**) stack_bottom - thread_stack) - { - fprintf(stderr, "Bogus stack limit or frame pointer,\ - fp=%p, stack_bottom=%p, thread_stack=%ld, aborting backtrace.\n", - fp, stack_bottom, thread_stack); - return; - } - - fprintf(stderr, "Stack range sanity check OK, backtrace follows:\n"); -#if defined(__alpha__) && defined(__GNUC__) - fprintf(stderr, "Warning: Alpha stacks are difficult -\ - will be taking some wild guesses, stack trace may be incorrect or \ - terminate abruptly\n"); - /* On Alpha, we need to get pc */ - __asm __volatile__ ("bsr %0, do_next; do_next: " - :"=r"(pc) - :"r"(pc)); -#endif /* __alpha__ */ - - /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */ - sigreturn_frame_count = thd_lib_detected == THD_LIB_LT ? 2 : 1; - - while (fp < (uchar**) stack_bottom) - { -#if defined(__i386__) || defined(__x86_64__) - uchar** new_fp = (uchar**)*fp; - fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ? - *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1)); -#endif /* defined(__386__) || defined(__x86_64__) */ - -#if defined(__alpha__) && defined(__GNUC__) - uchar** new_fp = find_prev_fp(pc, fp); - if (frame_count == sigreturn_frame_count - 1) - { - new_fp += 90; - } - - if (fp && pc) - { - pc = find_prev_pc(pc, fp); - if (pc) - fprintf(stderr, "%p\n", pc); - else - { - fprintf(stderr, "Not smart enough to deal with the rest\ - of this stack\n"); - goto end; - } - } - else - { - fprintf(stderr, "Not smart enough to deal with the rest of this stack\n"); - goto end; - } -#endif /* defined(__alpha__) && defined(__GNUC__) */ - if (new_fp <= fp ) - { - fprintf(stderr, "New value of fp=%p failed sanity check,\ - terminating stack trace!\n", new_fp); - goto end; - } - fp = new_fp; - ++frame_count; - } - - fprintf(stderr, "Stack trace seems successful - bottom reached\n"); - -end: - fprintf(stderr, - "Please read http://dev.mysql.com/doc/refman/5.1/en/resolve-stack-dump.html\n" - "and follow instructions on how to resolve the stack trace.\n" - "Resolved stack trace is much more helpful in diagnosing the\n" - "problem, so please do resolve it\n"); -} -#endif /* TARGET_OS_LINUX */ -#endif /* HAVE_STACKTRACE */ - -/* Produce a core for the thread */ -void my_write_core(int sig) -{ -#ifdef HAVE_gcov - extern void __gcov_flush(void); -#endif - signal(sig, SIG_DFL); -#ifdef HAVE_gcov - /* - For GCOV build, crashing will prevent the writing of code coverage - information from this process, causing gcov output to be incomplete. - So we force the writing of coverage information here before terminating. - */ - __gcov_flush(); -#endif - pthread_kill(pthread_self(), sig); -#if defined(P_MYID) && !defined(SCO) - /* On Solaris, the above kill is not enough */ - sigsend(P_PID,P_MYID,sig); -#endif -} - -#else /* __WIN__*/ - -#include <dbghelp.h> -#include <tlhelp32.h> -#if _MSC_VER -#pragma comment(lib, "dbghelp") -#endif - -static EXCEPTION_POINTERS *exception_ptrs; - -#define MODULE64_SIZE_WINXP 576 -#define STACKWALK_MAX_FRAMES 64 - -void my_init_stacktrace() -{ -} - - -void my_set_exception_pointers(EXCEPTION_POINTERS *ep) -{ - exception_ptrs = ep; -} - -/* - Appends directory to symbol path. -*/ -static void add_to_symbol_path(char *path, size_t path_buffer_size, - char *dir, size_t dir_buffer_size) -{ - strcat_s(dir, dir_buffer_size, ";"); - if (!strstr(path, dir)) - { - strcat_s(path, path_buffer_size, dir); - } -} - -/* - Get symbol path - semicolon-separated list of directories to search for debug - symbols. We expect PDB in the same directory as corresponding exe or dll, - so the path is build from directories of the loaded modules. If environment - variable _NT_SYMBOL_PATH is set, it's value appended to the symbol search path -*/ -static void get_symbol_path(char *path, size_t size) -{ - HANDLE hSnap; - char *envvar; - char *p; -#ifndef DBUG_OFF - static char pdb_debug_dir[MAX_PATH + 7]; -#endif - - path[0]= '\0'; - -#ifndef DBUG_OFF - /* - Add "debug" subdirectory of the application directory, sometimes PDB will - placed here by installation. - */ - GetModuleFileName(NULL, pdb_debug_dir, MAX_PATH); - p= strrchr(pdb_debug_dir, '\\'); - if(p) - { - *p= 0; - strcat_s(pdb_debug_dir, sizeof(pdb_debug_dir), "\\debug;"); - add_to_symbol_path(path, size, pdb_debug_dir, sizeof(pdb_debug_dir)); - } -#endif - - /* - Enumerate all modules, and add their directories to the path. - Avoid duplicate entries. - */ - hSnap= CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); - if (hSnap != INVALID_HANDLE_VALUE) - { - BOOL ret; - MODULEENTRY32 mod; - mod.dwSize= sizeof(MODULEENTRY32); - for (ret= Module32First(hSnap, &mod); ret; ret= Module32Next(hSnap, &mod)) - { - char *module_dir= mod.szExePath; - p= strrchr(module_dir,'\\'); - if (!p) - { - /* - Path separator was not found. Not known to happen, if ever happens, - will indicate current directory. - */ - module_dir[0]= '.'; - module_dir[1]= '\0'; - } - else - { - *p= '\0'; - } - add_to_symbol_path(path, size, module_dir,sizeof(mod.szExePath)); - } - CloseHandle(hSnap); - } - - - /* Add _NT_SYMBOL_PATH, if present. */ - envvar= getenv("_NT_SYMBOL_PATH"); - if(envvar) - { - strcat_s(path, size, envvar); - } -} - -#define MAX_SYMBOL_PATH 32768 - -/* Platform SDK in VS2003 does not have definition for SYMOPT_NO_PROMPTS*/ -#ifndef SYMOPT_NO_PROMPTS -#define SYMOPT_NO_PROMPTS 0 -#endif - -void my_print_stacktrace(uchar* unused1, ulong unused2) -{ - HANDLE hProcess= GetCurrentProcess(); - HANDLE hThread= GetCurrentThread(); - static IMAGEHLP_MODULE64 module= {sizeof(module)}; - static IMAGEHLP_SYMBOL64_PACKAGE package; - DWORD64 addr; - DWORD machine; - int i; - CONTEXT context; - STACKFRAME64 frame={0}; - static char symbol_path[MAX_SYMBOL_PATH]; - - if(!exception_ptrs) - return; - - /* Copy context, as stackwalking on original will unwind the stack */ - context = *(exception_ptrs->ContextRecord); - /*Initialize symbols.*/ - SymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG); - get_symbol_path(symbol_path, sizeof(symbol_path)); - SymInitialize(hProcess, symbol_path, TRUE); - - /*Prepare stackframe for the first StackWalk64 call*/ - frame.AddrFrame.Mode= frame.AddrPC.Mode= frame.AddrStack.Mode= AddrModeFlat; -#if (defined _M_IX86) - machine= IMAGE_FILE_MACHINE_I386; - frame.AddrFrame.Offset= context.Ebp; - frame.AddrPC.Offset= context.Eip; - frame.AddrStack.Offset= context.Esp; -#elif (defined _M_X64) - machine = IMAGE_FILE_MACHINE_AMD64; - frame.AddrFrame.Offset= context.Rbp; - frame.AddrPC.Offset= context.Rip; - frame.AddrStack.Offset= context.Rsp; -#else - /*There is currently no need to support IA64*/ -#pragma error ("unsupported architecture") -#endif - - package.sym.SizeOfStruct= sizeof(package.sym); - package.sym.MaxNameLength= sizeof(package.name); - - /*Walk the stack, output useful information*/ - for(i= 0; i< STACKWALK_MAX_FRAMES;i++) - { - DWORD64 function_offset= 0; - DWORD line_offset= 0; - IMAGEHLP_LINE64 line= {sizeof(line)}; - BOOL have_module= FALSE; - BOOL have_symbol= FALSE; - BOOL have_source= FALSE; - - if(!StackWalk64(machine, hProcess, hThread, &frame, &context, 0, 0, 0 ,0)) - break; - addr= frame.AddrPC.Offset; - - have_module= SymGetModuleInfo64(hProcess,addr,&module); -#ifdef _M_IX86 - if(!have_module) - { - /* - ModuleInfo structure has been "compatibly" extended in releases after XP, - and its size was increased. To make XP dbghelp.dll function - happy, pretend passing the old structure. - */ - module.SizeOfStruct= MODULE64_SIZE_WINXP; - have_module= SymGetModuleInfo64(hProcess, addr, &module); - } -#endif - - have_symbol= SymGetSymFromAddr64(hProcess, addr, &function_offset, - &(package.sym)); - have_source= SymGetLineFromAddr64(hProcess, addr, &line_offset, &line); - - fprintf(stderr, "%p ", addr); - if(have_module) - { - char *base_image_name= strrchr(module.ImageName, '\\'); - if(base_image_name) - base_image_name++; - else - base_image_name= module.ImageName; - fprintf(stderr, "%s!", base_image_name); - } - if(have_symbol) - fprintf(stderr, "%s()", package.sym.Name); - else if(have_module) - fprintf(stderr, "???"); - - if(have_source) - { - char *base_file_name= strrchr(line.FileName, '\\'); - if(base_file_name) - base_file_name++; - else - base_file_name= line.FileName; - fprintf(stderr,"[%s:%u]", base_file_name, line.LineNumber); - } - fprintf(stderr, "\n"); - } - fflush(stderr); -} - - -/* - Write dump. The dump is created in current directory, - file name is constructed from executable name plus - ".dmp" extension -*/ -void my_write_core(int unused) -{ - char path[MAX_PATH]; - char dump_fname[MAX_PATH]= "core.dmp"; - MINIDUMP_EXCEPTION_INFORMATION info; - HANDLE hFile; - - if(!exception_ptrs) - return; - - info.ExceptionPointers= exception_ptrs; - info.ClientPointers= FALSE; - info.ThreadId= GetCurrentThreadId(); - - if(GetModuleFileName(NULL, path, sizeof(path))) - { - _splitpath(path, NULL, NULL,dump_fname,NULL); - strncat(dump_fname, ".dmp", sizeof(dump_fname)); - } - - hFile= CreateFile(dump_fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, 0); - if(hFile) - { - /* Create minidump */ - if(MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), - hFile, MiniDumpNormal, &info, 0, 0)) - { - fprintf(stderr, "Minidump written to %s\n", - _fullpath(path, dump_fname, sizeof(path)) ? path : dump_fname); - } - else - { - fprintf(stderr,"MiniDumpWriteDump() failed, last error %u\n", - GetLastError()); - } - CloseHandle(hFile); - } - else - { - fprintf(stderr, "CreateFile(%s) failed, last error %u\n", dump_fname, - GetLastError()); - } - fflush(stderr); -} - - -void my_safe_print_str(const char *val, int len) -{ - __try - { - fprintf(stderr,"=%.*s\n", len, val); - } - __except(EXCEPTION_EXECUTE_HANDLER) - { - fprintf(stderr,"is an invalid string pointer\n"); - } -} -#endif /*__WIN__*/ diff --git a/dep/mysqllite/mysys/string.c b/dep/mysqllite/mysys/string.c deleted file mode 100644 index b1eded0664c..00000000000 --- a/dep/mysqllite/mysys/string.c +++ /dev/null @@ -1,182 +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 */ - -/* - Code for handling strings with can grow dynamicly. - Copyright Monty Program KB. - By monty. -*/ - -#include "mysys_priv.h" -#include <m_string.h> - -my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str, - size_t init_alloc, size_t alloc_increment) -{ - size_t length; - DBUG_ENTER("init_dynamic_string"); - - if (!alloc_increment) - alloc_increment=128; - length=1; - if (init_str && (length= strlen(init_str)+1) < init_alloc) - init_alloc=((length+alloc_increment-1)/alloc_increment)*alloc_increment; - if (!init_alloc) - init_alloc=alloc_increment; - - if (!(str->str=(char*) my_malloc(init_alloc,MYF(MY_WME)))) - DBUG_RETURN(TRUE); - str->length=length-1; - if (init_str) - memcpy(str->str,init_str,length); - str->max_length=init_alloc; - str->alloc_increment=alloc_increment; - DBUG_RETURN(FALSE); -} - - -my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str) -{ - uint length=0; - DBUG_ENTER("dynstr_set"); - - if (init_str && (length= (uint) strlen(init_str)+1) > str->max_length) - { - str->max_length=((length+str->alloc_increment-1)/str->alloc_increment)* - str->alloc_increment; - if (!str->max_length) - str->max_length=str->alloc_increment; - if (!(str->str=(char*) my_realloc(str->str,str->max_length,MYF(MY_WME)))) - DBUG_RETURN(TRUE); - } - if (init_str) - { - str->length=length-1; - memcpy(str->str,init_str,length); - } - else - str->length=0; - DBUG_RETURN(FALSE); -} - - -my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size) -{ - DBUG_ENTER("dynstr_realloc"); - - if (!additional_size) DBUG_RETURN(FALSE); - if (str->length + additional_size > str->max_length) - { - str->max_length=((str->length + additional_size+str->alloc_increment-1)/ - str->alloc_increment)*str->alloc_increment; - if (!(str->str=(char*) my_realloc(str->str,str->max_length,MYF(MY_WME)))) - DBUG_RETURN(TRUE); - } - DBUG_RETURN(FALSE); -} - - -my_bool dynstr_append(DYNAMIC_STRING *str, const char *append) -{ - return dynstr_append_mem(str,append,(uint) strlen(append)); -} - - -my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, - size_t length) -{ - char *new_ptr; - if (str->length+length >= str->max_length) - { - size_t new_length=(str->length+length+str->alloc_increment)/ - str->alloc_increment; - new_length*=str->alloc_increment; - if (!(new_ptr=(char*) my_realloc(str->str,new_length,MYF(MY_WME)))) - return TRUE; - str->str=new_ptr; - str->max_length=new_length; - } - memcpy(str->str + str->length,append,length); - str->length+=length; - str->str[str->length]=0; /* Safety for C programs */ - return FALSE; -} - - -my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n) -{ - str->length-=n; - str->str[str->length]= '\0'; - return FALSE; -} - -/* - Concatenates any number of strings, escapes any OS quote in the result then - surround the whole affair in another set of quotes which is finally appended - to specified DYNAMIC_STRING. This function is especially useful when - building strings to be executed with the system() function. - - @param str Dynamic String which will have addtional strings appended. - @param append String to be appended. - @param ... Optional. Additional string(s) to be appended. - - @note The final argument in the list must be NullS even if no additional - options are passed. - - @return True = Success. -*/ - -my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) -{ -#ifdef __WIN__ - const char *quote_str= "\""; - const uint quote_len= 1; -#else - const char *quote_str= "\'"; - const uint quote_len= 1; -#endif /* __WIN__ */ - my_bool ret= TRUE; - va_list dirty_text; - - ret&= dynstr_append_mem(str, quote_str, quote_len); /* Leading quote */ - va_start(dirty_text, append); - while (append != NullS) - { - const char *cur_pos= append; - const char *next_pos= cur_pos; - - /* Search for quote in each string and replace with escaped quote */ - while(*(next_pos= strcend(cur_pos, quote_str[0])) != '\0') - { - ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos)); - ret&= dynstr_append_mem(str ,"\\", 1); - ret&= dynstr_append_mem(str, quote_str, quote_len); - cur_pos= next_pos + 1; - } - ret&= dynstr_append_mem(str, cur_pos, (uint) (next_pos - cur_pos)); - append= va_arg(dirty_text, char *); - } - va_end(dirty_text); - ret&= dynstr_append_mem(str, quote_str, quote_len); /* Trailing quote */ - - return ret; -} - - -void dynstr_free(DYNAMIC_STRING *str) -{ - my_free(str->str); - str->str= NULL; -} diff --git a/dep/mysqllite/mysys/thr_alarm.c b/dep/mysqllite/mysys/thr_alarm.c deleted file mode 100644 index 2e427f96bdd..00000000000 --- a/dep/mysqllite/mysys/thr_alarm.c +++ /dev/null @@ -1,972 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* To avoid problems with alarms in debug code, we disable DBUG here */ -#define FORCE_DBUG_OFF -#include "mysys_priv.h" -#include <my_global.h> - -#if !defined(DONT_USE_THR_ALARM) -#include <errno.h> -#include <my_pthread.h> -#include <signal.h> -#include <my_sys.h> -#include <m_string.h> -#include <queues.h> -#include "thr_alarm.h" - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> /* AIX needs this for fd_set */ -#endif - -#ifndef ETIME -#define ETIME ETIMEDOUT -#endif - -uint thr_client_alarm; -static int alarm_aborted=1; /* No alarm thread */ -my_bool thr_alarm_inited= 0; -volatile my_bool alarm_thread_running= 0; -time_t next_alarm_expire_time= ~ (time_t) 0; -static sig_handler process_alarm_part2(int sig); - -#if !defined(__WIN__) - -static mysql_mutex_t LOCK_alarm; -static mysql_cond_t COND_alarm; -static sigset_t full_signal_set; -static QUEUE alarm_queue; -static uint max_used_alarms=0; -pthread_t alarm_thread; - -#ifdef USE_ALARM_THREAD -static void *alarm_handler(void *arg); -#define reschedule_alarms() mysql_cond_signal(&COND_alarm) -#else -#define reschedule_alarms() pthread_kill(alarm_thread,THR_SERVER_ALARM) -#endif - -static sig_handler thread_alarm(int sig __attribute__((unused))); - -static int compare_ulong(void *not_used __attribute__((unused)), - uchar *a_ptr,uchar* b_ptr) -{ - ulong a=*((ulong*) a_ptr),b= *((ulong*) b_ptr); - return (a < b) ? -1 : (a == b) ? 0 : 1; -} - -void init_thr_alarm(uint max_alarms) -{ - sigset_t s; - DBUG_ENTER("init_thr_alarm"); - alarm_aborted=0; - next_alarm_expire_time= ~ (time_t) 0; - init_queue(&alarm_queue,max_alarms+1,offsetof(ALARM,expire_time),0, - compare_ulong,NullS); - sigfillset(&full_signal_set); /* Neaded to block signals */ - mysql_mutex_init(key_LOCK_alarm, &LOCK_alarm, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_COND_alarm, &COND_alarm, NULL); - if (thd_lib_detected == THD_LIB_LT) - thr_client_alarm= SIGALRM; - else - thr_client_alarm= SIGUSR1; -#ifndef USE_ALARM_THREAD - if (thd_lib_detected != THD_LIB_LT) -#endif - { - my_sigset(thr_client_alarm, thread_alarm); - } - sigemptyset(&s); - sigaddset(&s, THR_SERVER_ALARM); - alarm_thread=pthread_self(); -#if defined(USE_ALARM_THREAD) - { - pthread_attr_t thr_attr; - pthread_attr_init(&thr_attr); - pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); - pthread_attr_setstacksize(&thr_attr,8196); - mysql_thread_create(key_thread_alarm, - &alarm_thread, &thr_attr, alarm_handler, NULL); - pthread_attr_destroy(&thr_attr); - } -#elif defined(USE_ONE_SIGNAL_HAND) - pthread_sigmask(SIG_BLOCK, &s, NULL); /* used with sigwait() */ - if (thd_lib_detected == THD_LIB_LT) - { - my_sigset(thr_client_alarm, process_alarm); /* Linuxthreads */ - pthread_sigmask(SIG_UNBLOCK, &s, NULL); - } -#else - my_sigset(THR_SERVER_ALARM, process_alarm); - pthread_sigmask(SIG_UNBLOCK, &s, NULL); -#endif - DBUG_VOID_RETURN; -} - - -void resize_thr_alarm(uint max_alarms) -{ - mysql_mutex_lock(&LOCK_alarm); - /* - It's ok not to shrink the queue as there may be more pending alarms than - than max_alarms - */ - if (alarm_queue.elements < max_alarms) - resize_queue(&alarm_queue,max_alarms+1); - mysql_mutex_unlock(&LOCK_alarm); -} - - -/* - Request alarm after sec seconds. - - SYNOPSIS - thr_alarm() - alrm Pointer to alarm detection - alarm_data Structure to store in alarm queue - - NOTES - This function can't be called from the alarm-handling thread. - - RETURN VALUES - 0 ok - 1 If no more alarms are allowed (aborted by process) - - Stores in first argument a pointer to a non-zero int which is set to 0 - when the alarm has been given -*/ - -my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) -{ - time_t now; -#ifndef USE_ONE_SIGNAL_HAND - sigset_t old_mask; -#endif - my_bool reschedule; - struct st_my_thread_var *current_my_thread_var= my_thread_var; - DBUG_ENTER("thr_alarm"); - DBUG_PRINT("enter",("thread: %s sec: %d",my_thread_name(),sec)); - - now= my_time(0); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); -#endif - mysql_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ - if (alarm_aborted > 0) - { /* No signal thread */ - DBUG_PRINT("info", ("alarm aborted")); - *alrm= 0; /* No alarm */ - mysql_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - DBUG_RETURN(1); - } - if (alarm_aborted < 0) - sec= 1; /* Abort mode */ - - if (alarm_queue.elements >= max_used_alarms) - { - if (alarm_queue.elements == alarm_queue.max_elements) - { - DBUG_PRINT("info", ("alarm queue full")); - fprintf(stderr,"Warning: thr_alarm queue is full\n"); - *alrm= 0; /* No alarm */ - mysql_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - DBUG_RETURN(1); - } - max_used_alarms=alarm_queue.elements+1; - } - reschedule= (ulong) next_alarm_expire_time > (ulong) now + sec; - if (!alarm_data) - { - if (!(alarm_data=(ALARM*) my_malloc(sizeof(ALARM),MYF(MY_WME)))) - { - DBUG_PRINT("info", ("failed my_malloc()")); - *alrm= 0; /* No alarm */ - mysql_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - DBUG_RETURN(1); - } - alarm_data->malloced=1; - } - else - alarm_data->malloced=0; - alarm_data->expire_time=now+sec; - alarm_data->alarmed=0; - alarm_data->thread= current_my_thread_var->pthread_self; - alarm_data->thread_id= current_my_thread_var->id; - queue_insert(&alarm_queue,(uchar*) alarm_data); - - /* Reschedule alarm if the current one has more than sec left */ - if (reschedule) - { - DBUG_PRINT("info", ("reschedule")); - if (pthread_equal(pthread_self(),alarm_thread)) - { - alarm(sec); /* purecov: inspected */ - next_alarm_expire_time= now + sec; - } - else - reschedule_alarms(); /* Reschedule alarms */ - } - mysql_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - (*alrm)= &alarm_data->alarmed; - DBUG_RETURN(0); -} - - -/* - Remove alarm from list of alarms -*/ - -void thr_end_alarm(thr_alarm_t *alarmed) -{ - ALARM *alarm_data; -#ifndef USE_ONE_SIGNAL_HAND - sigset_t old_mask; -#endif - uint i, found=0; - DBUG_ENTER("thr_end_alarm"); - -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); -#endif - mysql_mutex_lock(&LOCK_alarm); - - alarm_data= (ALARM*) ((uchar*) *alarmed - offsetof(ALARM,alarmed)); - for (i=0 ; i < alarm_queue.elements ; i++) - { - if ((ALARM*) queue_element(&alarm_queue,i) == alarm_data) - { - queue_remove(&alarm_queue,i),MYF(0); - if (alarm_data->malloced) - my_free(alarm_data); - found++; -#ifdef DBUG_OFF - break; -#endif - } - } - DBUG_ASSERT(!*alarmed || found == 1); - if (!found) - { - if (*alarmed) - fprintf(stderr,"Warning: Didn't find alarm 0x%lx in queue of %d alarms\n", - (long) *alarmed, alarm_queue.elements); - DBUG_PRINT("warning",("Didn't find alarm 0x%lx in queue\n", - (long) *alarmed)); - } - mysql_mutex_unlock(&LOCK_alarm); -#ifndef USE_ONE_SIGNAL_HAND - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - DBUG_VOID_RETURN; -} - -/* - Come here when some alarm in queue is due. - Mark all alarms with are finnished in list. - Shedule alarms to be sent again after 1-10 sec (many alarms at once) - If alarm_aborted is set then all alarms are given and resent - every second. -*/ - -sig_handler process_alarm(int sig __attribute__((unused))) -{ - sigset_t old_mask; -/* - This must be first as we can't call DBUG inside an alarm for a normal thread -*/ - - if (thd_lib_detected == THD_LIB_LT && - !pthread_equal(pthread_self(),alarm_thread)) - { -#if defined(MAIN) && !defined(__bsdi__) - printf("thread_alarm in process_alarm\n"); fflush(stdout); -#endif -#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY - my_sigset(thr_client_alarm, process_alarm); /* int. thread system calls */ -#endif - return; - } - - /* - We have to do do the handling of the alarm in a sub function, - because otherwise we would get problems with two threads calling - DBUG_... functions at the same time (as two threads may call - process_alarm() at the same time - */ - -#ifndef USE_ALARM_THREAD - pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask); - mysql_mutex_lock(&LOCK_alarm); -#endif - process_alarm_part2(sig); -#ifndef USE_ALARM_THREAD -#if defined(SIGNAL_HANDLER_RESET_ON_DELIVERY) && !defined(USE_ONE_SIGNAL_HAND) - my_sigset(THR_SERVER_ALARM,process_alarm); -#endif - mysql_mutex_unlock(&LOCK_alarm); - pthread_sigmask(SIG_SETMASK,&old_mask,NULL); -#endif - return; -} - - -static sig_handler process_alarm_part2(int sig __attribute__((unused))) -{ - ALARM *alarm_data; - DBUG_ENTER("process_alarm"); - DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements)); - -#if defined(MAIN) && !defined(__bsdi__) - printf("process_alarm\n"); fflush(stdout); -#endif - if (alarm_queue.elements) - { - if (alarm_aborted) - { - uint i; - for (i=0 ; i < alarm_queue.elements ;) - { - alarm_data=(ALARM*) queue_element(&alarm_queue,i); - alarm_data->alarmed=1; /* Info to thread */ - if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, thr_client_alarm)) - { -#ifdef MAIN - printf("Warning: pthread_kill couldn't find thread!!!\n"); -#endif - queue_remove(&alarm_queue,i); /* No thread. Remove alarm */ - } - else - i++; /* Signal next thread */ - } -#ifndef USE_ALARM_THREAD - if (alarm_queue.elements) - alarm(1); /* Signal soon again */ -#endif - } - else - { - ulong now=(ulong) my_time(0); - ulong next=now+10-(now%10); - while ((alarm_data=(ALARM*) queue_top(&alarm_queue))->expire_time <= now) - { - alarm_data->alarmed=1; /* Info to thread */ - DBUG_PRINT("info",("sending signal to waiting thread")); - if (pthread_equal(alarm_data->thread,alarm_thread) || - pthread_kill(alarm_data->thread, thr_client_alarm)) - { -#ifdef MAIN - printf("Warning: pthread_kill couldn't find thread!!!\n"); -#endif - queue_remove(&alarm_queue,0); /* No thread. Remove alarm */ - if (!alarm_queue.elements) - break; - } - else - { - alarm_data->expire_time=next; - queue_replaced(&alarm_queue); - } - } -#ifndef USE_ALARM_THREAD - if (alarm_queue.elements) - { -#ifdef __bsdi__ - alarm(0); /* Remove old alarm */ -#endif - alarm((uint) (alarm_data->expire_time-now)); - next_alarm_expire_time= alarm_data->expire_time; - } -#endif - } - } - else - { - /* - Ensure that next time we call thr_alarm(), we will schedule a new alarm - */ - next_alarm_expire_time= ~(time_t) 0; - } - DBUG_VOID_RETURN; -} - - -/* - Schedule all alarms now and optionally free all structures - - SYNPOSIS - end_thr_alarm() - free_structures Set to 1 if we should free memory used for - the alarm queue. - When we call this we should KNOW that there - is no active alarms - IMPLEMENTATION - Set alarm_abort to -1 which will change the behavior of alarms as follows: - - All old alarms will be rescheduled at once - - All new alarms will be rescheduled to one second -*/ - -void end_thr_alarm(my_bool free_structures) -{ - DBUG_ENTER("end_thr_alarm"); - if (alarm_aborted != 1) /* If memory not freed */ - { - mysql_mutex_lock(&LOCK_alarm); - DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); - alarm_aborted= -1; /* mark aborted */ - if (alarm_queue.elements || (alarm_thread_running && free_structures)) - { - if (pthread_equal(pthread_self(),alarm_thread)) - alarm(1); /* Shut down everything soon */ - else - reschedule_alarms(); - } - if (free_structures) - { - struct timespec abstime; - - DBUG_ASSERT(!alarm_queue.elements); - - /* Wait until alarm thread dies */ - set_timespec(abstime, 10); /* Wait up to 10 seconds */ - while (alarm_thread_running) - { - int error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime); - if (error == ETIME || error == ETIMEDOUT) - break; /* Don't wait forever */ - } - delete_queue(&alarm_queue); - alarm_aborted= 1; - mysql_mutex_unlock(&LOCK_alarm); - if (!alarm_thread_running) /* Safety */ - { - mysql_mutex_destroy(&LOCK_alarm); - mysql_cond_destroy(&COND_alarm); - } - } - else - mysql_mutex_unlock(&LOCK_alarm); - } - DBUG_VOID_RETURN; -} - - -/* - Remove another thread from the alarm -*/ - -void thr_alarm_kill(my_thread_id thread_id) -{ - uint i; - if (alarm_aborted) - return; - mysql_mutex_lock(&LOCK_alarm); - for (i=0 ; i < alarm_queue.elements ; i++) - { - if (((ALARM*) queue_element(&alarm_queue,i))->thread_id == thread_id) - { - ALARM *tmp=(ALARM*) queue_remove(&alarm_queue,i); - tmp->expire_time=0; - queue_insert(&alarm_queue,(uchar*) tmp); - reschedule_alarms(); - break; - } - } - mysql_mutex_unlock(&LOCK_alarm); -} - - -void thr_alarm_info(ALARM_INFO *info) -{ - mysql_mutex_lock(&LOCK_alarm); - info->next_alarm_time= 0; - info->max_used_alarms= max_used_alarms; - if ((info->active_alarms= alarm_queue.elements)) - { - ulong now=(ulong) my_time(0); - long time_diff; - ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue); - time_diff= (long) (alarm_data->expire_time - now); - info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff); - } - mysql_mutex_unlock(&LOCK_alarm); -} - -/* - This is here for thread to get interruptet from read/write/fcntl - ARGSUSED -*/ - - -static sig_handler thread_alarm(int sig __attribute__((unused))) -{ -#ifdef MAIN - printf("thread_alarm\n"); fflush(stdout); -#endif -#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY - my_sigset(sig,thread_alarm); /* int. thread system calls */ -#endif -} - - -#ifdef HAVE_TIMESPEC_TS_SEC -#define tv_sec ts_sec -#define tv_nsec ts_nsec -#endif - -/* set up a alarm thread with uses 'sleep' to sleep between alarms */ - -#ifdef USE_ALARM_THREAD -static void *alarm_handler(void *arg __attribute__((unused))) -{ - int error; - struct timespec abstime; -#ifdef MAIN - puts("Starting alarm thread"); -#endif - my_thread_init(); - alarm_thread_running= 1; - mysql_mutex_lock(&LOCK_alarm); - for (;;) - { - if (alarm_queue.elements) - { - ulong sleep_time,now= my_time(0); - if (alarm_aborted) - sleep_time=now+1; - else - sleep_time= ((ALARM*) queue_top(&alarm_queue))->expire_time; - if (sleep_time > now) - { - abstime.tv_sec=sleep_time; - abstime.tv_nsec=0; - next_alarm_expire_time= sleep_time; - if ((error= mysql_cond_timedwait(&COND_alarm, &LOCK_alarm, &abstime)) && - error != ETIME && error != ETIMEDOUT) - { -#ifdef MAIN - printf("Got error: %d from ptread_cond_timedwait (errno: %d)\n", - error,errno); -#endif - } - } - } - else if (alarm_aborted == -1) - break; - else - { - next_alarm_expire_time= ~ (time_t) 0; - if ((error= mysql_cond_wait(&COND_alarm, &LOCK_alarm))) - { -#ifdef MAIN - printf("Got error: %d from ptread_cond_wait (errno: %d)\n", - error,errno); -#endif - } - } - process_alarm(0); - } - bzero((char*) &alarm_thread,sizeof(alarm_thread)); /* For easy debugging */ - alarm_thread_running= 0; - mysql_cond_signal(&COND_alarm); - mysql_mutex_unlock(&LOCK_alarm); - pthread_exit(0); - return 0; /* Impossible */ -} -#endif /* USE_ALARM_THREAD */ - -/***************************************************************************** - thr_alarm for win95 -*****************************************************************************/ - -#else /* __WIN__ */ - -void thr_alarm_kill(my_thread_id thread_id) -{ - /* Can't do this yet */ -} - -sig_handler process_alarm(int sig __attribute__((unused))) -{ - /* Can't do this yet */ -} - - -my_bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm) -{ - (*alrm)= &alarm->alarmed; - if (alarm_aborted) - { - alarm->alarmed.crono=0; - return 1; - } - if (!(alarm->alarmed.crono=SetTimer((HWND) NULL,0, sec*1000, - (TIMERPROC) NULL))) - return 1; - return 0; -} - - -my_bool thr_got_alarm(thr_alarm_t *alrm_ptr) -{ - thr_alarm_t alrm= *alrm_ptr; - MSG msg; - if (alrm->crono) - { - PeekMessage(&msg,NULL,WM_TIMER,WM_TIMER,PM_REMOVE) ; - if (msg.message == WM_TIMER || alarm_aborted) - { - KillTimer(NULL, alrm->crono); - alrm->crono = 0; - } - } - return !alrm->crono || alarm_aborted; -} - - -void thr_end_alarm(thr_alarm_t *alrm_ptr) -{ - thr_alarm_t alrm= *alrm_ptr; - /* alrm may be zero if thr_alarm aborted with an error */ - if (alrm && alrm->crono) - - { - KillTimer(NULL, alrm->crono); - alrm->crono = 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) -{ -} - -#endif /* __WIN__ */ - -#endif - -/**************************************************************************** - Handling of test case (when compiled with -DMAIN) -***************************************************************************/ - -#ifdef MAIN -#if !defined(DONT_USE_THR_ALARM) - -static mysql_cond_t COND_thread_count; -static mysql_mutex_t LOCK_thread_count; -static uint thread_count; - -#ifdef HPUX10 -typedef int * fd_set_ptr; -#else -typedef fd_set * fd_set_ptr; -#endif /* HPUX10 */ - -static void *test_thread(void *arg) -{ - int i,param=*((int*) arg),wait_time,retry; - time_t start_time; - thr_alarm_t got_alarm; - fd_set fd; - FD_ZERO(&fd); - my_thread_init(); - printf("Thread %d (%s) started\n",param,my_thread_name()); fflush(stdout); - for (i=1 ; i <= 10 ; i++) - { - wait_time=param ? 11-i : i; - start_time= my_time(0); - if (thr_alarm(&got_alarm,wait_time,0)) - { - printf("Thread: %s Alarms aborted\n",my_thread_name()); - break; - } - if (wait_time == 3) - { - printf("Thread: %s Simulation of no alarm needed\n",my_thread_name()); - fflush(stdout); - } - else - { - for (retry=0 ; !thr_got_alarm(&got_alarm) && retry < 10 ; retry++) - { - printf("Thread: %s Waiting %d sec\n",my_thread_name(),wait_time); - select(0,(fd_set_ptr) &fd,0,0,0); - } - if (!thr_got_alarm(&got_alarm)) - { - printf("Thread: %s didn't get an alarm. Aborting!\n", - my_thread_name()); - break; - } - if (wait_time == 7) - { /* Simulate alarm-miss */ - fd_set readFDs; - uint max_connection=fileno(stdin); - FD_ZERO(&readFDs); - FD_SET(max_connection,&readFDs); - retry=0; - for (;;) - { - printf("Thread: %s Simulating alarm miss\n",my_thread_name()); - fflush(stdout); - if (select(max_connection+1, (fd_set_ptr) &readFDs,0,0,0) < 0) - { - if (errno == EINTR) - break; /* Got new interrupt */ - printf("Got errno: %d from select. Retrying..\n",errno); - if (retry++ >= 3) - { - printf("Warning: Interrupt of select() doesn't set errno!\n"); - break; - } - } - else /* This shouldn't happen */ - { - if (!FD_ISSET(max_connection,&readFDs)) - { - printf("Select interrupted, but errno not set\n"); - fflush(stdout); - if (retry++ >= 3) - break; - continue; - } - (void) getchar(); /* Somebody was playing */ - } - } - } - } - printf("Thread: %s Slept for %d (%d) sec\n",my_thread_name(), - (int) (my_time(0)-start_time), wait_time); fflush(stdout); - thr_end_alarm(&got_alarm); - fflush(stdout); - } - mysql_mutex_lock(&LOCK_thread_count); - thread_count--; - mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ - mysql_mutex_unlock(&LOCK_thread_count); - free((uchar*) arg); - return 0; -} - -#ifdef USE_ONE_SIGNAL_HAND -static sig_handler print_signal_warning(int sig) -{ - printf("Warning: Got signal %d from thread %s\n",sig,my_thread_name()); - fflush(stdout); -#ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY - my_sigset(sig,print_signal_warning); /* int. thread system calls */ -#endif - if (sig == SIGALRM) - alarm(2); /* reschedule alarm */ -} -#endif /* USE_ONE_SIGNAL_HAND */ - - -static void *signal_hand(void *arg __attribute__((unused))) -{ - sigset_t set; - int sig,error,err_count=0;; - - my_thread_init(); - pthread_detach_this_thread(); - init_thr_alarm(10); /* Setup alarm handler */ - mysql_mutex_lock(&LOCK_thread_count); /* Required by bsdi */ - mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ - mysql_mutex_unlock(&LOCK_thread_count); - - sigemptyset(&set); /* Catch all signals */ - sigaddset(&set,SIGINT); - sigaddset(&set,SIGQUIT); - sigaddset(&set,SIGTERM); - sigaddset(&set,SIGHUP); -#ifdef SIGTSTP - sigaddset(&set,SIGTSTP); -#endif -#ifdef USE_ONE_SIGNAL_HAND - sigaddset(&set,THR_SERVER_ALARM); /* For alarms */ - puts("Starting signal and alarm handling thread"); -#else - puts("Starting signal handling thread"); -#endif - printf("server alarm: %d thread alarm: %d\n", - THR_SERVER_ALARM, thr_client_alarm); - DBUG_PRINT("info",("Starting signal and alarm handling thread")); - for(;;) - { - while ((error=my_sigwait(&set,&sig)) == EINTR) - printf("sigwait restarted\n"); - if (error) - { - fprintf(stderr,"Got error %d from sigwait\n",error); - if (err_count++ > 5) - exit(1); /* Too many errors in test */ - continue; - } -#ifdef USE_ONE_SIGNAL_HAND - if (sig != THR_SERVER_ALARM) -#endif - printf("Main thread: Got signal %d\n",sig); - switch (sig) { - case SIGINT: - case SIGQUIT: - case SIGTERM: - case SIGHUP: - printf("Aborting nicely\n"); - end_thr_alarm(0); - break; -#ifdef SIGTSTP - case SIGTSTP: - printf("Aborting\n"); - exit(1); - return 0; /* Keep some compilers happy */ -#endif -#ifdef USE_ONE_SIGNAL_HAND - case THR_SERVER_ALARM: - process_alarm(sig); - break; -#endif - } - } -} - - -int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) -{ - pthread_t tid; - pthread_attr_t thr_attr; - int i,*param,error; - sigset_t set; - ALARM_INFO alarm_info; - MY_INIT(argv[0]); - - if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') - { - DBUG_PUSH(argv[1]+2); - } - mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST); - mysql_cond_init(0, &COND_thread_count, NULL); - - /* Start a alarm handling thread */ - sigemptyset(&set); - sigaddset(&set,SIGINT); - sigaddset(&set,SIGQUIT); - sigaddset(&set,SIGTERM); - sigaddset(&set,SIGHUP); - signal(SIGTERM,SIG_DFL); /* If it's blocked by parent */ -#ifdef SIGTSTP - sigaddset(&set,SIGTSTP); -#endif - sigaddset(&set,THR_SERVER_ALARM); - sigdelset(&set, thr_client_alarm); - (void) pthread_sigmask(SIG_SETMASK,&set,NULL); - - pthread_attr_init(&thr_attr); - pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); - pthread_attr_setstacksize(&thr_attr,65536L); - - /* Start signal thread and wait for it to start */ - mysql_mutex_lock(&LOCK_thread_count); - mysql_thread_create(0, - &tid, &thr_attr, signal_hand, NULL); - mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - mysql_mutex_unlock(&LOCK_thread_count); - DBUG_PRINT("info",("signal thread created")); - - thr_setconcurrency(3); - pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS); - printf("Main thread: %s\n",my_thread_name()); - for (i=0 ; i < 2 ; i++) - { - param=(int*) malloc(sizeof(int)); - *param= i; - mysql_mutex_lock(&LOCK_thread_count); - if ((error= mysql_thread_create(0, - &tid, &thr_attr, test_thread, - (void*) param))) - { - printf("Can't create thread %d, error: %d\n",i,error); - exit(1); - } - thread_count++; - mysql_mutex_unlock(&LOCK_thread_count); - } - - pthread_attr_destroy(&thr_attr); - mysql_mutex_lock(&LOCK_thread_count); - thr_alarm_info(&alarm_info); - 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); - while (thread_count) - { - mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); - if (thread_count == 1) - { - printf("Calling end_thr_alarm. This should cancel the last thread\n"); - end_thr_alarm(0); - } - } - mysql_mutex_unlock(&LOCK_thread_count); - 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); - printf("Test succeeded\n"); - return 0; -} - -#else /* !defined(DONT_USE_ALARM_THREAD) */ - -int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) -{ - printf("thr_alarm disabled with DONT_USE_THR_ALARM\n"); - exit(1); -} - -#endif /* !defined(DONT_USE_ALARM_THREAD) */ -#endif /* MAIN */ diff --git a/dep/mysqllite/mysys/thr_lock.c b/dep/mysqllite/mysys/thr_lock.c deleted file mode 100644 index 2ab283e068d..00000000000 --- a/dep/mysqllite/mysys/thr_lock.c +++ /dev/null @@ -1,1688 +0,0 @@ -/* Copyright (C) 2000 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* -Read and write locks for Posix threads. All tread must acquire -all locks it needs through thr_multi_lock() to avoid dead-locks. -A lock consists of a master lock (THR_LOCK), and lock instances -(THR_LOCK_DATA). -Any thread can have any number of lock instances (read and write:s) on -any lock. All lock instances must be freed. -Locks are prioritized according to: - -The current lock types are: - -TL_READ # Low priority read -TL_READ_WITH_SHARED_LOCKS -TL_READ_HIGH_PRIORITY # High priority read -TL_READ_NO_INSERT # Read without concurrent inserts -TL_WRITE_ALLOW_WRITE # Write lock that allows other writers -TL_WRITE_CONCURRENT_INSERT - # Insert that can be mixed when selects -TL_WRITE_DELAYED # Used by delayed insert - # Allows lower locks to take over -TL_WRITE_LOW_PRIORITY # Low priority write -TL_WRITE # High priority write -TL_WRITE_ONLY # High priority write - # Abort all new lock request with an error - -Locks are prioritized according to: - -WRITE_ALLOW_WRITE, WRITE_CONCURRENT_INSERT, WRITE_DELAYED, -WRITE_LOW_PRIORITY, READ, WRITE, READ_HIGH_PRIORITY and WRITE_ONLY - -Locks in the same privilege level are scheduled in first-in-first-out order. - -To allow concurrent read/writes locks, with 'WRITE_CONCURRENT_INSERT' one -should put a pointer to the following functions in the lock structure: -(If the pointer is zero (default), the function is not called) - -check_status: - Before giving a lock of type TL_WRITE_CONCURRENT_INSERT, - we check if this function exists and returns 0. - If not, then the lock is upgraded to TL_WRITE_LOCK - In MyISAM this is a simple check if the insert can be done - at the end of the datafile. -update_status: - Before a write lock is released, this function is called. - In MyISAM this functions updates the count and length of the datafile -get_status: - When one gets a lock this functions is called. - In MyISAM this stores the number of rows and size of the datafile - for concurrent reads. - -The lock algorithm allows one to have one TL_WRITE_CONCURRENT_INSERT or -one TL_WRITE_DELAYED lock at the same time as multiple read locks. - -*/ - -#if !defined(MAIN) && !defined(DBUG_OFF) && !defined(EXTRA_DEBUG) -#define FORCE_DBUG_OFF -#endif - -#include "mysys_priv.h" - -#include "thr_lock.h" -#include <m_string.h> -#include <errno.h> - -my_bool thr_lock_inited=0; -ulong locks_immediate = 0L, locks_waited = 0L; -enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE; - -/* The following constants are only for debug output */ -#define MAX_THREADS 100 -#define MAX_LOCKS 100 - - -LIST *thr_lock_thread_list; /* List of threads in use */ -ulong max_write_lock_count= ~(ulong) 0L; - -static void (*before_lock_wait)(void)= 0; -static void (*after_lock_wait)(void)= 0; - -void thr_set_lock_wait_callback(void (*before_wait)(void), - void (*after_wait)(void)) -{ - before_lock_wait= before_wait; - after_lock_wait= after_wait; -} - -static inline mysql_cond_t *get_cond(void) -{ - return &my_thread_var->suspend; -} - -/* -** For the future (now the thread specific cond is alloced by my_pthread.c) -*/ - -my_bool init_thr_lock() -{ - thr_lock_inited=1; - return 0; -} - -static inline my_bool -thr_lock_owner_equal(THR_LOCK_INFO *rhs, THR_LOCK_INFO *lhs) -{ - return rhs == lhs; -} - - -#ifdef EXTRA_DEBUG -#define MAX_FOUND_ERRORS 10 /* Report 10 first errors */ -static uint found_errors=0; - -static int check_lock(struct st_lock_list *list, const char* lock_type, - const char *where, my_bool same_owner, my_bool no_cond) -{ - THR_LOCK_DATA *data,**prev; - uint count=0; - THR_LOCK_INFO *UNINIT_VAR(first_owner); - - prev= &list->data; - if (list->data) - { - enum thr_lock_type last_lock_type=list->data->type; - - if (same_owner && list->data) - first_owner= list->data->owner; - for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) - { - if (data->type != last_lock_type) - last_lock_type=TL_IGNORE; - if (data->prev != prev) - { - fprintf(stderr, - "Warning: prev link %d didn't point at previous lock at %s: %s\n", - count, lock_type, where); - return 1; - } - if (same_owner && - !thr_lock_owner_equal(data->owner, first_owner) && - last_lock_type != TL_WRITE_ALLOW_WRITE) - { - fprintf(stderr, - "Warning: Found locks from different threads in %s: %s\n", - lock_type,where); - return 1; - } - if (no_cond && data->cond) - { - fprintf(stderr, - "Warning: Found active lock with not reset cond %s: %s\n", - lock_type,where); - return 1; - } - prev= &data->next; - } - if (data) - { - fprintf(stderr,"Warning: found too many locks at %s: %s\n", - lock_type,where); - return 1; - } - } - if (prev != list->last) - { - fprintf(stderr,"Warning: last didn't point at last lock at %s: %s\n", - lock_type, where); - return 1; - } - return 0; -} - - -static void check_locks(THR_LOCK *lock, const char *where, - my_bool allow_no_locks) -{ - uint old_found_errors=found_errors; - DBUG_ENTER("check_locks"); - - if (found_errors < MAX_FOUND_ERRORS) - { - if (check_lock(&lock->write,"write",where,1,1) | - check_lock(&lock->write_wait,"write_wait",where,0,0) | - check_lock(&lock->read,"read",where,0,1) | - check_lock(&lock->read_wait,"read_wait",where,0,0)) - found_errors++; - - if (found_errors < MAX_FOUND_ERRORS) - { - uint count=0; - THR_LOCK_DATA *data; - for (data=lock->read.data ; data ; data=data->next) - { - if ((int) data->type == (int) TL_READ_NO_INSERT) - count++; - /* Protect against infinite loop. */ - DBUG_ASSERT(count <= lock->read_no_write_count); - } - if (count != lock->read_no_write_count) - { - found_errors++; - fprintf(stderr, - "Warning at '%s': Locks read_no_write_count was %u when it should have been %u\n", where, lock->read_no_write_count,count); - } - - if (!lock->write.data) - { - if (!allow_no_locks && !lock->read.data && - (lock->write_wait.data || lock->read_wait.data)) - { - found_errors++; - fprintf(stderr, - "Warning at '%s': No locks in use but locks are in wait queue\n", - where); - } - if (!lock->write_wait.data) - { - if (!allow_no_locks && lock->read_wait.data) - { - found_errors++; - fprintf(stderr, - "Warning at '%s': No write locks and waiting read locks\n", - where); - } - } - else - { - if (!allow_no_locks && - (((lock->write_wait.data->type == TL_WRITE_CONCURRENT_INSERT || - lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) && - !lock->read_no_write_count) || - (lock->write_wait.data->type == TL_WRITE_DELAYED && - !lock->read.data))) - { - found_errors++; - fprintf(stderr, - "Warning at '%s': Write lock %d waiting while no exclusive read locks\n",where,(int) lock->write_wait.data->type); - } - } - } - else - { /* Have write lock */ - if (lock->write_wait.data) - { - if (!allow_no_locks && - lock->write.data->type == TL_WRITE_ALLOW_WRITE && - lock->write_wait.data->type == TL_WRITE_ALLOW_WRITE) - { - found_errors++; - fprintf(stderr, - "Warning at '%s': Found WRITE_ALLOW_WRITE lock waiting for WRITE_ALLOW_WRITE lock\n", - where); - } - } - if (lock->read.data) - { - if (!thr_lock_owner_equal(lock->write.data->owner, - lock->read.data->owner) && - ((lock->write.data->type > TL_WRITE_DELAYED && - lock->write.data->type != TL_WRITE_ONLY) || - ((lock->write.data->type == TL_WRITE_CONCURRENT_INSERT || - lock->write.data->type == TL_WRITE_ALLOW_WRITE) && - lock->read_no_write_count))) - { - found_errors++; - fprintf(stderr, - "Warning at '%s': Found lock of type %d that is write and read locked\n", - where, lock->write.data->type); - DBUG_PRINT("warning",("At '%s': Found lock of type %d that is write and read locked\n", - where, lock->write.data->type)); - - } - } - if (lock->read_wait.data) - { - if (!allow_no_locks && lock->write.data->type <= TL_WRITE_DELAYED && - lock->read_wait.data->type <= TL_READ_HIGH_PRIORITY) - { - found_errors++; - fprintf(stderr, - "Warning at '%s': Found read lock of type %d waiting for write lock of type %d\n", - where, - (int) lock->read_wait.data->type, - (int) lock->write.data->type); - } - } - } - } - if (found_errors != old_found_errors) - { - DBUG_PRINT("error",("Found wrong lock")); - } - } - DBUG_VOID_RETURN; -} - -#else /* EXTRA_DEBUG */ -#define check_locks(A,B,C) -#endif - - - /* Initialize a lock */ - -void thr_lock_init(THR_LOCK *lock) -{ - DBUG_ENTER("thr_lock_init"); - bzero((char*) lock,sizeof(*lock)); - mysql_mutex_init(key_THR_LOCK_mutex, &lock->mutex, MY_MUTEX_INIT_FAST); - lock->read.last= &lock->read.data; - lock->read_wait.last= &lock->read_wait.data; - lock->write_wait.last= &lock->write_wait.data; - lock->write.last= &lock->write.data; - - mysql_mutex_lock(&THR_LOCK_lock); /* Add to locks in use */ - lock->list.data=(void*) lock; - thr_lock_thread_list=list_add(thr_lock_thread_list,&lock->list); - mysql_mutex_unlock(&THR_LOCK_lock); - DBUG_VOID_RETURN; -} - - -void thr_lock_delete(THR_LOCK *lock) -{ - DBUG_ENTER("thr_lock_delete"); - mysql_mutex_lock(&THR_LOCK_lock); - thr_lock_thread_list=list_delete(thr_lock_thread_list,&lock->list); - mysql_mutex_unlock(&THR_LOCK_lock); - mysql_mutex_destroy(&lock->mutex); - DBUG_VOID_RETURN; -} - - -void thr_lock_info_init(THR_LOCK_INFO *info) -{ - struct st_my_thread_var *tmp= my_thread_var; - info->thread= tmp->pthread_self; - info->thread_id= tmp->id; -} - - /* Initialize a lock instance */ - -void thr_lock_data_init(THR_LOCK *lock,THR_LOCK_DATA *data, void *param) -{ - data->lock=lock; - data->type=TL_UNLOCK; - data->owner= 0; /* no owner yet */ - data->status_param=param; - data->cond=0; -} - - -static inline my_bool -has_old_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner) -{ - for ( ; data ; data=data->next) - { - if (thr_lock_owner_equal(data->owner, owner)) - return 1; /* Already locked by thread */ - } - return 0; -} - -static inline my_bool have_specific_lock(THR_LOCK_DATA *data, - enum thr_lock_type type) -{ - for ( ; data ; data=data->next) - { - if (data->type == type) - return 1; - } - return 0; -} - - -static void wake_up_waiters(THR_LOCK *lock); - - -static enum enum_thr_lock_result -wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data, - my_bool in_wait_list, ulong lock_wait_timeout) -{ - struct st_my_thread_var *thread_var= my_thread_var; - mysql_cond_t *cond= &thread_var->suspend; - struct timespec wait_timeout; - enum enum_thr_lock_result result= THR_LOCK_ABORTED; - const char *old_proc_info; - DBUG_ENTER("wait_for_lock"); - - /* - One can use this to signal when a thread is going to wait for a lock. - See debug_sync.cc. - - Beware of waiting for a signal here. The lock has aquired its mutex. - While waiting on a signal here, the locking thread could not aquire - the mutex to release the lock. One could lock up the table - completely. - - In detail it works so: When thr_lock() tries to acquire a table - lock, it locks the lock->mutex, checks if it can have the lock, and - if not, it calls wait_for_lock(). Here it unlocks the table lock - while waiting on a condition. The sync point is located before this - wait for condition. If we have a waiting action here, we hold the - the table locks mutex all the time. Any attempt to look at the table - lock by another thread blocks it immediately on lock->mutex. This - can easily become an unexpected and unobvious blockage. So be - warned: Do not request a WAIT_FOR action for the 'wait_for_lock' - sync point unless you really know what you do. - */ - DEBUG_SYNC_C("wait_for_lock"); - - if (!in_wait_list) - { - (*wait->last)=data; /* Wait for lock */ - data->prev= wait->last; - wait->last= &data->next; - } - - statistic_increment(locks_waited, &THR_LOCK_lock); - - /* Set up control struct to allow others to abort locks */ - thread_var->current_mutex= &data->lock->mutex; - thread_var->current_cond= cond; - data->cond= cond; - - old_proc_info= proc_info_hook(NULL, "Waiting for table level lock", - __func__, __FILE__, __LINE__); - - /* - Since before_lock_wait potentially can create more threads to - scheduler work for, we don't want to call the before_lock_wait - callback unless it will really start to wait. - - For similar reasons, we do not want to call before_lock_wait and - after_lock_wait for each lap around the loop, so we restrict - ourselves to call it before_lock_wait once before starting to wait - and once after the thread has exited the wait loop. - */ - if ((!thread_var->abort || in_wait_list) && before_lock_wait) - (*before_lock_wait)(); - - set_timespec(wait_timeout, lock_wait_timeout); - while (!thread_var->abort || in_wait_list) - { - int rc= mysql_cond_timedwait(cond, &data->lock->mutex, &wait_timeout); - /* - We must break the wait if one of the following occurs: - - the connection has been aborted (!thread_var->abort), but - this is not a delayed insert thread (in_wait_list). For a delayed - insert thread the proper action at shutdown is, apparently, to - acquire the lock and complete the insert. - - the lock has been granted (data->cond is set to NULL by the granter), - or the waiting has been aborted (additionally data->type is set to - TL_UNLOCK). - - the wait has timed out (rc == ETIMEDOUT) - Order of checks below is important to not report about timeout - if the predicate is true. - */ - if (data->cond == 0) - { - DBUG_PRINT("thr_lock", ("lock granted/aborted")); - break; - } - if (rc == ETIMEDOUT || rc == ETIME) - { - /* purecov: begin inspected */ - DBUG_PRINT("thr_lock", ("lock timed out")); - result= THR_LOCK_WAIT_TIMEOUT; - break; - /* purecov: end */ - } - } - - /* - We call the after_lock_wait callback once the wait loop has - finished. - */ - if (after_lock_wait) - (*after_lock_wait)(); - - DBUG_PRINT("thr_lock", ("aborted: %d in_wait_list: %d", - thread_var->abort, in_wait_list)); - - if (data->cond || data->type == TL_UNLOCK) - { - if (data->cond) /* aborted or timed out */ - { - if (((*data->prev)=data->next)) /* remove from wait-list */ - data->next->prev= data->prev; - else - wait->last=data->prev; - data->type= TL_UNLOCK; /* No lock */ - check_locks(data->lock, "killed or timed out wait_for_lock", 1); - wake_up_waiters(data->lock); - } - else - { - DBUG_PRINT("thr_lock", ("lock aborted")); - check_locks(data->lock, "aborted wait_for_lock", 0); - } - } - else - { - result= THR_LOCK_SUCCESS; - if (data->lock->get_status) - (*data->lock->get_status)(data->status_param, 0); - check_locks(data->lock,"got wait_for_lock",0); - } - mysql_mutex_unlock(&data->lock->mutex); - - /* The following must be done after unlock of lock->mutex */ - mysql_mutex_lock(&thread_var->mutex); - thread_var->current_mutex= 0; - thread_var->current_cond= 0; - mysql_mutex_unlock(&thread_var->mutex); - - proc_info_hook(NULL, old_proc_info, __func__, __FILE__, __LINE__); - - DBUG_RETURN(result); -} - - -enum enum_thr_lock_result -thr_lock(THR_LOCK_DATA *data, THR_LOCK_INFO *owner, - enum thr_lock_type lock_type, ulong lock_wait_timeout) -{ - THR_LOCK *lock=data->lock; - enum enum_thr_lock_result result= THR_LOCK_SUCCESS; - struct st_lock_list *wait_queue; - DBUG_ENTER("thr_lock"); - - data->next=0; - data->cond=0; /* safety */ - data->type=lock_type; - data->owner= owner; /* Must be reset ! */ - mysql_mutex_lock(&lock->mutex); - DBUG_PRINT("lock",("data: 0x%lx thread: 0x%lx lock: 0x%lx type: %d", - (long) data, data->owner->thread_id, - (long) lock, (int) lock_type)); - check_locks(lock,(uint) lock_type <= (uint) TL_READ_NO_INSERT ? - "enter read_lock" : "enter write_lock",0); - if ((int) lock_type <= (int) TL_READ_NO_INSERT) - { - /* Request for READ lock */ - if (lock->write.data) - { - /* - We can allow a read lock even if there is already a - write lock on the table if they are owned by the same - thread or if they satisfy the following lock - compatibility matrix: - - Request - /------- - H|++++ WRITE_ALLOW_WRITE - e|+++- WRITE_CONCURRENT_INSERT - l|++++ WRITE_DELAYED - d |||| - |||\= READ_NO_INSERT - ||\ = READ_HIGH_PRIORITY - |\ = READ_WITH_SHARED_LOCKS - \ = READ - - - + = Request can be satisified. - - = Request cannot be satisified. - - READ_NO_INSERT and WRITE_ALLOW_WRITE should in principle - be incompatible. However this will cause starvation of - LOCK TABLE READ in InnoDB under high write load. - See Bug#42147 for more information. - */ - - DBUG_PRINT("lock",("write locked 1 by thread: 0x%lx", - lock->write.data->owner->thread_id)); - if (thr_lock_owner_equal(data->owner, lock->write.data->owner) || - (lock->write.data->type <= TL_WRITE_DELAYED && - (((int) lock_type <= (int) TL_READ_HIGH_PRIORITY) || - (lock->write.data->type != TL_WRITE_CONCURRENT_INSERT)))) - { /* Already got a write lock */ - (*lock->read.last)=data; /* Add to running FIFO */ - data->prev=lock->read.last; - lock->read.last= &data->next; - if (lock_type == TL_READ_NO_INSERT) - lock->read_no_write_count++; - check_locks(lock,"read lock with old write lock",0); - if (lock->get_status) - (*lock->get_status)(data->status_param, 0); - statistic_increment(locks_immediate,&THR_LOCK_lock); - goto end; - } - if (lock->write.data->type == TL_WRITE_ONLY) - { - /* We are not allowed to get a READ lock in this case */ - data->type=TL_UNLOCK; - result= THR_LOCK_ABORTED; /* Can't wait for this one */ - goto end; - } - } - else if (!lock->write_wait.data || - lock->write_wait.data->type <= TL_WRITE_LOW_PRIORITY || - lock_type == TL_READ_HIGH_PRIORITY || - has_old_lock(lock->read.data, data->owner)) /* Has old read lock */ - { /* No important write-locks */ - (*lock->read.last)=data; /* Add to running FIFO */ - data->prev=lock->read.last; - lock->read.last= &data->next; - if (lock->get_status) - (*lock->get_status)(data->status_param, 0); - if (lock_type == TL_READ_NO_INSERT) - lock->read_no_write_count++; - check_locks(lock,"read lock with no write locks",0); - statistic_increment(locks_immediate,&THR_LOCK_lock); - goto end; - } - /* - We're here if there is an active write lock or no write - lock but a high priority write waiting in the write_wait queue. - In the latter case we should yield the lock to the writer. - */ - wait_queue= &lock->read_wait; - } - else /* Request for WRITE lock */ - { - if (lock_type == TL_WRITE_DELAYED) - { - if (lock->write.data && lock->write.data->type == TL_WRITE_ONLY) - { - data->type=TL_UNLOCK; - result= THR_LOCK_ABORTED; /* Can't wait for this one */ - goto end; - } - if (lock->write.data || lock->read.data) - { - /* Add delayed write lock to write_wait queue, and return at once */ - (*lock->write_wait.last)=data; - data->prev=lock->write_wait.last; - lock->write_wait.last= &data->next; - data->cond=get_cond(); - /* - We don't have to do get_status here as we will do it when we change - the delayed lock to a real write lock - */ - statistic_increment(locks_immediate,&THR_LOCK_lock); - goto end; - } - } - else if (lock_type == TL_WRITE_CONCURRENT_INSERT && ! lock->check_status) - data->type=lock_type= thr_upgraded_concurrent_insert_lock; - - if (lock->write.data) /* If there is a write lock */ - { - if (lock->write.data->type == TL_WRITE_ONLY) - { - /* purecov: begin tested */ - /* Allow lock owner to bypass TL_WRITE_ONLY. */ - if (!thr_lock_owner_equal(data->owner, lock->write.data->owner)) - { - /* We are not allowed to get a lock in this case */ - data->type=TL_UNLOCK; - result= THR_LOCK_ABORTED; /* Can't wait for this one */ - goto end; - } - /* purecov: end */ - } - - /* - The idea is to allow us to get a lock at once if we already have - a write lock or if there is no pending write locks and if all - write locks are of TL_WRITE_ALLOW_WRITE type. - - Note that, since lock requests for the same table are sorted in - such way that requests with higher thr_lock_type value come first - (with one exception (*)), lock being requested usually (**) has - equal or "weaker" type than one which thread might have already - acquired. - *) The only exception to this rule is case when type of old lock - is TL_WRITE_LOW_PRIORITY and type of new lock is changed inside - of thr_lock() from TL_WRITE_CONCURRENT_INSERT to TL_WRITE since - engine turns out to be not supporting concurrent inserts. - Note that since TL_WRITE has the same compatibility rules as - TL_WRITE_LOW_PRIORITY (their only difference is priority), - it is OK to grant new lock without additional checks in such - situation. - **) The exceptions are situations when: - - when old lock type is TL_WRITE_DELAYED - But these should never happen within MySQL. - Therefore it is OK to allow acquiring write lock on the table if - this thread already holds some write lock on it. - - (INSERT INTO t1 VALUES (f1()), where f1() is stored function which - tries to update t1, is an example of statement which requests two - different types of write lock on the same table). - */ - DBUG_ASSERT(! has_old_lock(lock->write.data, data->owner) || - ((lock_type <= lock->write.data->type || - (lock_type == TL_WRITE && - lock->write.data->type == TL_WRITE_LOW_PRIORITY)) && - lock->write.data->type != TL_WRITE_DELAYED)); - - if ((lock_type == TL_WRITE_ALLOW_WRITE && - ! lock->write_wait.data && - lock->write.data->type == TL_WRITE_ALLOW_WRITE) || - has_old_lock(lock->write.data, data->owner)) - { - /* - We have already got a write lock or all locks are - TL_WRITE_ALLOW_WRITE - */ - DBUG_PRINT("info", ("write_wait.data: 0x%lx old_type: %d", - (ulong) lock->write_wait.data, - lock->write.data->type)); - - (*lock->write.last)=data; /* Add to running fifo */ - data->prev=lock->write.last; - lock->write.last= &data->next; - check_locks(lock,"second write lock",0); - if (data->lock->get_status) - (*data->lock->get_status)(data->status_param, 0); - statistic_increment(locks_immediate,&THR_LOCK_lock); - goto end; - } - DBUG_PRINT("lock",("write locked 2 by thread: 0x%lx", - lock->write.data->owner->thread_id)); - } - else - { - DBUG_PRINT("info", ("write_wait.data: 0x%lx", - (ulong) lock->write_wait.data)); - if (!lock->write_wait.data) - { /* no scheduled write locks */ - my_bool concurrent_insert= 0; - if (lock_type == TL_WRITE_CONCURRENT_INSERT) - { - concurrent_insert= 1; - if ((*lock->check_status)(data->status_param)) - { - concurrent_insert= 0; - data->type=lock_type= thr_upgraded_concurrent_insert_lock; - } - } - - if (!lock->read.data || - (lock_type <= TL_WRITE_DELAYED && - ((lock_type != TL_WRITE_CONCURRENT_INSERT && - lock_type != TL_WRITE_ALLOW_WRITE) || - !lock->read_no_write_count))) - { - (*lock->write.last)=data; /* Add as current write lock */ - data->prev=lock->write.last; - lock->write.last= &data->next; - if (data->lock->get_status) - (*data->lock->get_status)(data->status_param, concurrent_insert); - check_locks(lock,"only write lock",0); - statistic_increment(locks_immediate,&THR_LOCK_lock); - goto end; - } - } - DBUG_PRINT("lock",("write locked 3 by thread: 0x%lx type: %d", - lock->read.data->owner->thread_id, data->type)); - } - wait_queue= &lock->write_wait; - } - /* Can't get lock yet; Wait for it */ - DBUG_RETURN(wait_for_lock(wait_queue, data, 0, lock_wait_timeout)); -end: - mysql_mutex_unlock(&lock->mutex); - DBUG_RETURN(result); -} - - -static inline void free_all_read_locks(THR_LOCK *lock, - my_bool using_concurrent_insert) -{ - THR_LOCK_DATA *data=lock->read_wait.data; - - check_locks(lock,"before freeing read locks",1); - - /* move all locks from read_wait list to read list */ - (*lock->read.last)=data; - data->prev=lock->read.last; - lock->read.last=lock->read_wait.last; - - /* Clear read_wait list */ - lock->read_wait.last= &lock->read_wait.data; - - do - { - mysql_cond_t *cond= data->cond; - if ((int) data->type == (int) TL_READ_NO_INSERT) - { - if (using_concurrent_insert) - { - /* - We can't free this lock; - Link lock away from read chain back into read_wait chain - */ - if (((*data->prev)=data->next)) - data->next->prev=data->prev; - else - lock->read.last=data->prev; - *lock->read_wait.last= data; - data->prev= lock->read_wait.last; - lock->read_wait.last= &data->next; - continue; - } - lock->read_no_write_count++; - } - /* purecov: begin inspected */ - DBUG_PRINT("lock",("giving read lock to thread: 0x%lx", - data->owner->thread_id)); - /* purecov: end */ - data->cond=0; /* Mark thread free */ - mysql_cond_signal(cond); - } while ((data=data->next)); - *lock->read_wait.last=0; - if (!lock->read_wait.data) - lock->write_lock_count=0; - check_locks(lock,"after giving read locks",0); -} - - /* Unlock lock and free next thread on same lock */ - -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: 0x%lx lock: 0x%lx", - (long) data, data->owner->thread_id, (long) lock)); - mysql_mutex_lock(&lock->mutex); - check_locks(lock,"start of release lock",0); - - if (((*data->prev)=data->next)) /* remove from lock-list */ - data->next->prev= data->prev; - else if (lock_type <= TL_READ_NO_INSERT) - lock->read.last=data->prev; - else if (lock_type == TL_WRITE_DELAYED && data->cond) - { - /* - This only happens in extreme circumstances when a - write delayed lock that is waiting for a lock - */ - lock->write_wait.last=data->prev; /* Put it on wait queue */ - } - else - lock->write.last=data->prev; - if (lock_type >= TL_WRITE_CONCURRENT_INSERT) - { - if (lock->update_status) - (*lock->update_status)(data->status_param); - } - else - { - if (lock->restore_status) - (*lock->restore_status)(data->status_param); - } - if (lock_type == TL_READ_NO_INSERT) - lock->read_no_write_count--; - data->type=TL_UNLOCK; /* Mark unlocked */ - check_locks(lock,"after releasing lock",1); - wake_up_waiters(lock); - mysql_mutex_unlock(&lock->mutex); - DBUG_VOID_RETURN; -} - - -/** - @brief Wake up all threads which pending requests for the lock - can be satisfied. - - @param lock Lock for which threads should be woken up - -*/ - -static void wake_up_waiters(THR_LOCK *lock) -{ - THR_LOCK_DATA *data; - enum thr_lock_type lock_type; - - DBUG_ENTER("wake_up_waiters"); - - if (!lock->write.data) /* If no active write locks */ - { - data=lock->write_wait.data; - if (!lock->read.data) /* If no more locks in use */ - { - /* Release write-locks with TL_WRITE or TL_WRITE_ONLY priority first */ - if (data && - (data->type != TL_WRITE_LOW_PRIORITY || !lock->read_wait.data || - lock->read_wait.data->type < TL_READ_HIGH_PRIORITY)) - { - if (lock->write_lock_count++ > max_write_lock_count) - { - /* Too many write locks in a row; Release all waiting read locks */ - lock->write_lock_count=0; - if (lock->read_wait.data) - { - DBUG_PRINT("info",("Freeing all read_locks because of max_write_lock_count")); - free_all_read_locks(lock,0); - goto end; - } - } - for (;;) - { - if (((*data->prev)=data->next)) /* remove from wait-list */ - data->next->prev= data->prev; - else - lock->write_wait.last=data->prev; - (*lock->write.last)=data; /* Put in execute list */ - data->prev=lock->write.last; - data->next=0; - lock->write.last= &data->next; - if (data->type == TL_WRITE_CONCURRENT_INSERT && - (*lock->check_status)(data->status_param)) - data->type=TL_WRITE; /* Upgrade lock */ - /* purecov: begin inspected */ - DBUG_PRINT("lock",("giving write lock of type %d to thread: 0x%lx", - data->type, data->owner->thread_id)); - /* purecov: end */ - { - mysql_cond_t *cond= data->cond; - data->cond=0; /* Mark thread free */ - mysql_cond_signal(cond); /* Start waiting thread */ - } - if (data->type != TL_WRITE_ALLOW_WRITE || - !lock->write_wait.data || - lock->write_wait.data->type != TL_WRITE_ALLOW_WRITE) - break; - data=lock->write_wait.data; /* Free this too */ - } - if (data->type >= TL_WRITE_LOW_PRIORITY) - goto end; - /* Release possible read locks together with the write lock */ - } - if (lock->read_wait.data) - free_all_read_locks(lock, - data && - (data->type == TL_WRITE_CONCURRENT_INSERT || - data->type == TL_WRITE_ALLOW_WRITE)); - else - { - DBUG_PRINT("lock",("No waiting read locks to free")); - } - } - else if (data && - (lock_type=data->type) <= TL_WRITE_DELAYED && - ((lock_type != TL_WRITE_CONCURRENT_INSERT && - lock_type != TL_WRITE_ALLOW_WRITE) || - !lock->read_no_write_count)) - { - /* - For DELAYED, ALLOW_READ, WRITE_ALLOW_WRITE or CONCURRENT_INSERT locks - start WRITE locks together with the READ locks - */ - if (lock_type == TL_WRITE_CONCURRENT_INSERT && - (*lock->check_status)(data->status_param)) - { - data->type=TL_WRITE; /* Upgrade lock */ - if (lock->read_wait.data) - free_all_read_locks(lock,0); - goto end; - } - do { - mysql_cond_t *cond= data->cond; - if (((*data->prev)=data->next)) /* remove from wait-list */ - data->next->prev= data->prev; - else - lock->write_wait.last=data->prev; - (*lock->write.last)=data; /* Put in execute list */ - data->prev=lock->write.last; - lock->write.last= &data->next; - data->next=0; /* Only one write lock */ - data->cond=0; /* Mark thread free */ - mysql_cond_signal(cond); /* Start waiting thread */ - } while (lock_type == TL_WRITE_ALLOW_WRITE && - (data=lock->write_wait.data) && - data->type == TL_WRITE_ALLOW_WRITE); - if (lock->read_wait.data) - free_all_read_locks(lock, - (lock_type == TL_WRITE_CONCURRENT_INSERT || - lock_type == TL_WRITE_ALLOW_WRITE)); - } - else if (!data && lock->read_wait.data) - free_all_read_locks(lock,0); - } -end: - check_locks(lock, "after waking up waiters", 0); - DBUG_VOID_RETURN; -} - - -/* -** Get all locks in a specific order to avoid dead-locks -** Sort acording to lock position and put write_locks before read_locks if -** lock on same lock. -*/ - - -#define LOCK_CMP(A,B) ((uchar*) (A->lock) - (uint) ((A)->type) < (uchar*) (B->lock)- (uint) ((B)->type)) - -static void sort_locks(THR_LOCK_DATA **data,uint count) -{ - THR_LOCK_DATA **pos,**end,**prev,*tmp; - - /* Sort locks with insertion sort (fast because almost always few locks) */ - - for (pos=data+1,end=data+count; pos < end ; pos++) - { - tmp= *pos; - if (LOCK_CMP(tmp,pos[-1])) - { - prev=pos; - do { - prev[0]=prev[-1]; - } while (--prev != data && LOCK_CMP(tmp,prev[-1])); - prev[0]=tmp; - } - } -} - - -enum enum_thr_lock_result -thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, - ulong lock_wait_timeout) -{ - THR_LOCK_DATA **pos,**end; - DBUG_ENTER("thr_multi_lock"); - DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count)); - if (count > 1) - sort_locks(data,count); - /* lock everything */ - for (pos=data,end=data+count; pos < end ; pos++) - { - enum enum_thr_lock_result result= thr_lock(*pos, owner, (*pos)->type, - lock_wait_timeout); - if (result != THR_LOCK_SUCCESS) - { /* Aborted */ - thr_multi_unlock(data,(uint) (pos-data)); - DBUG_RETURN(result); - } - DEBUG_SYNC_C("thr_multi_lock_after_thr_lock"); -#ifdef MAIN - printf("Thread: %s Got lock: 0x%lx type: %d\n",my_thread_name(), - (long) pos[0]->lock, pos[0]->type); fflush(stdout); -#endif - } - thr_lock_merge_status(data, count); - DBUG_RETURN(THR_LOCK_SUCCESS); -} - - -/** - Ensure that all locks for a given table have the same - status_param. - - This is a MyISAM and possibly Maria specific crutch. MyISAM - engine stores data file length, record count and other table - properties in status_param member of handler. When a table is - locked, connection-local copy is made from a global copy - (myisam_share) by mi_get_status(). When a table is unlocked, - the changed status is transferred back to the global share by - mi_update_status(). - - One thing MyISAM doesn't do is to ensure that when the same - table is opened twice in a connection all instances share the - same status_param. This is necessary, however: for one, to keep - all instances of a connection "on the same page" with regard to - the current state of the table. For other, unless this is done, - myisam_share will always get updated from the last unlocked - instance (in mi_update_status()), and when this instance was not - the one that was used to update data, records may be lost. - - For each table, this function looks up the last lock_data in the - list of acquired locks, and makes sure that all other instances - share status_param with it. -*/ - -void -thr_lock_merge_status(THR_LOCK_DATA **data, uint count) -{ -#if !defined(DONT_USE_RW_LOCKS) - THR_LOCK_DATA **pos= data; - THR_LOCK_DATA **end= data + count; - if (count > 1) - { - THR_LOCK_DATA *last_lock= end[-1]; - pos=end-1; - do - { - pos--; - if (last_lock->lock == (*pos)->lock && - last_lock->lock->copy_status) - { - if (last_lock->type <= TL_READ_NO_INSERT) - { - THR_LOCK_DATA **read_lock; - /* - If we are locking the same table with read locks we must ensure - that all tables share the status of the last write lock or - the same read lock. - */ - for (; - (*pos)->type <= TL_READ_NO_INSERT && - pos != data && - pos[-1]->lock == (*pos)->lock ; - pos--) ; - - read_lock = pos+1; - do - { - (last_lock->lock->copy_status)((*read_lock)->status_param, - (*pos)->status_param); - } while (*(read_lock++) != last_lock); - last_lock= (*pos); /* Point at last write lock */ - } - else - (*last_lock->lock->copy_status)((*pos)->status_param, - last_lock->status_param); - } - else - last_lock=(*pos); - } while (pos != data); - } -#endif -} - - /* free all locks */ - -void thr_multi_unlock(THR_LOCK_DATA **data,uint count) -{ - THR_LOCK_DATA **pos,**end; - DBUG_ENTER("thr_multi_unlock"); - DBUG_PRINT("lock",("data: 0x%lx count: %d", (long) data, count)); - - for (pos=data,end=data+count; pos < end ; pos++) - { -#ifdef MAIN - printf("Thread: %s Rel lock: 0x%lx type: %d\n", - my_thread_name(), (long) pos[0]->lock, pos[0]->type); - fflush(stdout); -#endif - if ((*pos)->type != TL_UNLOCK) - thr_unlock(*pos); - else - { - DBUG_PRINT("lock",("Free lock: data: 0x%lx thread: 0x%lx lock: 0x%lx", - (long) *pos, (*pos)->owner->thread_id, - (long) (*pos)->lock)); - } - } - DBUG_VOID_RETURN; -} - -/* - Abort all threads waiting for a lock. The lock will be upgraded to - TL_WRITE_ONLY to abort any new accesses to the lock -*/ - -void thr_abort_locks(THR_LOCK *lock, my_bool upgrade_lock) -{ - THR_LOCK_DATA *data; - DBUG_ENTER("thr_abort_locks"); - mysql_mutex_lock(&lock->mutex); - - for (data=lock->read_wait.data; data ; data=data->next) - { - data->type=TL_UNLOCK; /* Mark killed */ - /* It's safe to signal the cond first: we're still holding the mutex. */ - mysql_cond_signal(data->cond); - data->cond=0; /* Removed from list */ - } - for (data=lock->write_wait.data; data ; data=data->next) - { - data->type=TL_UNLOCK; - mysql_cond_signal(data->cond); - data->cond=0; - } - 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 (upgrade_lock && lock->write.data) - lock->write.data->type=TL_WRITE_ONLY; - mysql_mutex_unlock(&lock->mutex); - DBUG_VOID_RETURN; -} - - -/* - Abort all locks for specific table/thread combination - - This is used to abort all locks for a specific thread -*/ - -my_bool thr_abort_locks_for_thread(THR_LOCK *lock, my_thread_id thread_id) -{ - THR_LOCK_DATA *data; - my_bool found= FALSE; - DBUG_ENTER("thr_abort_locks_for_thread"); - - mysql_mutex_lock(&lock->mutex); - for (data= lock->read_wait.data; data ; data= data->next) - { - if (data->owner->thread_id == thread_id) /* purecov: tested */ - { - DBUG_PRINT("info",("Aborting read-wait lock")); - data->type= TL_UNLOCK; /* Mark killed */ - /* It's safe to signal the cond first: we're still holding the mutex. */ - found= TRUE; - mysql_cond_signal(data->cond); - data->cond= 0; /* Removed from list */ - - if (((*data->prev)= data->next)) - data->next->prev= data->prev; - else - lock->read_wait.last= data->prev; - } - } - for (data= lock->write_wait.data; data ; data= data->next) - { - if (data->owner->thread_id == thread_id) /* purecov: tested */ - { - DBUG_PRINT("info",("Aborting write-wait lock")); - data->type= TL_UNLOCK; - found= TRUE; - mysql_cond_signal(data->cond); - data->cond= 0; - - if (((*data->prev)= data->next)) - data->next->prev= data->prev; - else - lock->write_wait.last= data->prev; - } - } - wake_up_waiters(lock); - mysql_mutex_unlock(&lock->mutex); - DBUG_RETURN(found); -} - - -/* - 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. The normal downgrade variants are: - 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; -#ifndef DBUG_OFF - enum thr_lock_type old_lock_type= in_data->type; -#endif - DBUG_ENTER("thr_downgrade_write_only_lock"); - - mysql_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); - - mysql_mutex_unlock(&lock->mutex); - DBUG_VOID_RETURN; -} - -/* Upgrade a WRITE_DELAY lock to a WRITE_LOCK */ - -my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data, - enum thr_lock_type new_lock_type, - ulong lock_wait_timeout) -{ - THR_LOCK *lock=data->lock; - DBUG_ENTER("thr_upgrade_write_delay_lock"); - - mysql_mutex_lock(&lock->mutex); - if (data->type == TL_UNLOCK || data->type >= TL_WRITE_LOW_PRIORITY) - { - mysql_mutex_unlock(&lock->mutex); - DBUG_RETURN(data->type == TL_UNLOCK); /* Test if Aborted */ - } - check_locks(lock,"before upgrading lock",0); - /* TODO: Upgrade to TL_WRITE_CONCURRENT_INSERT in some cases */ - data->type= new_lock_type; /* Upgrade lock */ - - /* Check if someone has given us the lock */ - if (!data->cond) - { - if (!lock->read.data) /* No read locks */ - { /* We have the lock */ - if (data->lock->get_status) - (*data->lock->get_status)(data->status_param, 0); - mysql_mutex_unlock(&lock->mutex); - DBUG_RETURN(0); - } - - if (((*data->prev)=data->next)) /* remove from lock-list */ - data->next->prev= data->prev; - else - lock->write.last=data->prev; - - if ((data->next=lock->write_wait.data)) /* Put first in lock_list */ - data->next->prev= &data->next; - else - lock->write_wait.last= &data->next; - data->prev= &lock->write_wait.data; - lock->write_wait.data=data; - check_locks(lock,"upgrading lock",0); - } - else - { - check_locks(lock,"waiting for lock",0); - } - DBUG_RETURN(wait_for_lock(&lock->write_wait,data,1, lock_wait_timeout)); -} - - -/* downgrade a WRITE lock to a WRITE_DELAY lock if there is pending locks */ - -my_bool thr_reschedule_write_lock(THR_LOCK_DATA *data, - ulong lock_wait_timeout) -{ - THR_LOCK *lock=data->lock; - enum thr_lock_type write_lock_type; - DBUG_ENTER("thr_reschedule_write_lock"); - - mysql_mutex_lock(&lock->mutex); - if (!lock->read_wait.data) /* No waiting read locks */ - { - mysql_mutex_unlock(&lock->mutex); - DBUG_RETURN(0); - } - - write_lock_type= data->type; - data->type=TL_WRITE_DELAYED; - if (lock->update_status) - (*lock->update_status)(data->status_param); - if (((*data->prev)=data->next)) /* remove from lock-list */ - data->next->prev= data->prev; - else - lock->write.last=data->prev; - - if ((data->next=lock->write_wait.data)) /* Put first in lock_list */ - data->next->prev= &data->next; - else - lock->write_wait.last= &data->next; - data->prev= &lock->write_wait.data; - data->cond=get_cond(); /* This was zero */ - lock->write_wait.data=data; - free_all_read_locks(lock,0); - - mysql_mutex_unlock(&lock->mutex); - DBUG_RETURN(thr_upgrade_write_delay_lock(data, write_lock_type, - lock_wait_timeout)); -} - - -#include <my_sys.h> - -static void thr_print_lock(const char* name,struct st_lock_list *list) -{ - THR_LOCK_DATA *data,**prev; - uint count=0; - - if (list->data) - { - printf("%-10s: ",name); - prev= &list->data; - for (data=list->data; data && count++ < MAX_LOCKS ; data=data->next) - { - printf("0x%lx (%lu:%d); ", (ulong) data, data->owner->thread_id, - (int) data->type); - if (data->prev != prev) - printf("\nWarning: prev didn't point at previous lock\n"); - prev= &data->next; - } - puts(""); - if (prev != list->last) - printf("Warning: last didn't point at last lock\n"); - } -} - -void thr_print_locks(void) -{ - LIST *list; - uint count=0; - - mysql_mutex_lock(&THR_LOCK_lock); - puts("Current locks:"); - for (list= thr_lock_thread_list; list && count++ < MAX_THREADS; - list= list_rest(list)) - { - THR_LOCK *lock=(THR_LOCK*) list->data; - mysql_mutex_lock(&lock->mutex); - printf("lock: 0x%lx:",(ulong) lock); - if ((lock->write_wait.data || lock->read_wait.data) && - (! lock->read.data && ! lock->write.data)) - printf(" WARNING: "); - if (lock->write.data) - printf(" write"); - if (lock->write_wait.data) - printf(" write_wait"); - if (lock->read.data) - printf(" read"); - if (lock->read_wait.data) - printf(" read_wait"); - puts(""); - thr_print_lock("write",&lock->write); - thr_print_lock("write_wait",&lock->write_wait); - thr_print_lock("read",&lock->read); - thr_print_lock("read_wait",&lock->read_wait); - mysql_mutex_unlock(&lock->mutex); - puts(""); - } - fflush(stdout); - mysql_mutex_unlock(&THR_LOCK_lock); -} - - -/***************************************************************************** -** Test of thread locks -****************************************************************************/ - -#ifdef MAIN - -struct st_test { - uint lock_nr; - enum thr_lock_type lock_type; -}; - -THR_LOCK locks[5]; /* 4 locks */ - -struct st_test test_0[] = {{0,TL_READ}}; /* One lock */ -struct st_test test_1[] = {{0,TL_READ},{0,TL_WRITE}}; /* Read and write lock of lock 0 */ -struct st_test test_2[] = {{1,TL_WRITE},{0,TL_READ},{2,TL_READ}}; -struct st_test test_3[] = {{2,TL_WRITE},{1,TL_READ},{0,TL_READ}}; /* Deadlock with test_2 ? */ -struct st_test test_4[] = {{0,TL_WRITE},{0,TL_READ},{0,TL_WRITE},{0,TL_READ}}; -struct st_test test_5[] = {{0,TL_READ},{1,TL_READ},{2,TL_READ},{3,TL_READ}}; /* Many reads */ -struct st_test test_6[] = {{0,TL_WRITE},{1,TL_WRITE},{2,TL_WRITE},{3,TL_WRITE}}; /* Many writes */ -struct st_test test_7[] = {{3,TL_READ}}; -struct st_test test_8[] = {{1,TL_READ_NO_INSERT},{2,TL_READ_NO_INSERT},{3,TL_READ_NO_INSERT}}; /* Should be quick */ -struct st_test test_9[] = {{4,TL_READ_HIGH_PRIORITY}}; -struct st_test test_10[] ={{4,TL_WRITE}}; -struct st_test test_11[] = {{0,TL_WRITE_LOW_PRIORITY},{1,TL_WRITE_LOW_PRIORITY},{2,TL_WRITE_LOW_PRIORITY},{3,TL_WRITE_LOW_PRIORITY}}; /* Many writes */ -struct st_test test_12[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_WRITE_CONCURRENT_INSERT},{2,TL_WRITE_CONCURRENT_INSERT},{3,TL_WRITE_CONCURRENT_INSERT}}; -struct st_test test_13[] = {{0,TL_WRITE_CONCURRENT_INSERT},{1,TL_READ}}; -struct st_test test_14[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_READ}}; -struct st_test test_15[] = {{0,TL_WRITE_ALLOW_WRITE},{1,TL_WRITE_ALLOW_WRITE}}; - -struct st_test *tests[] = {test_0,test_1,test_2,test_3,test_4,test_5,test_6, - test_7,test_8,test_9,test_10,test_11,test_12, - test_13,test_14,test_15}; -int lock_counts[]= {sizeof(test_0)/sizeof(struct st_test), - sizeof(test_1)/sizeof(struct st_test), - sizeof(test_2)/sizeof(struct st_test), - sizeof(test_3)/sizeof(struct st_test), - sizeof(test_4)/sizeof(struct st_test), - sizeof(test_5)/sizeof(struct st_test), - sizeof(test_6)/sizeof(struct st_test), - sizeof(test_7)/sizeof(struct st_test), - sizeof(test_8)/sizeof(struct st_test), - sizeof(test_9)/sizeof(struct st_test), - sizeof(test_10)/sizeof(struct st_test), - sizeof(test_11)/sizeof(struct st_test), - sizeof(test_12)/sizeof(struct st_test), - sizeof(test_13)/sizeof(struct st_test), - sizeof(test_14)/sizeof(struct st_test), - sizeof(test_15)/sizeof(struct st_test) -}; - - -static mysql_cond_t COND_thread_count; -static mysql_mutex_t LOCK_thread_count; -static uint thread_count; -static ulong sum=0; - -#define MAX_LOCK_COUNT 8 -#define TEST_TIMEOUT 100000 - -/* The following functions is for WRITE_CONCURRENT_INSERT */ - -static void test_get_status(void* param __attribute__((unused)), - int concurrent_insert __attribute__((unused))) -{ -} - -static void test_update_status(void* param __attribute__((unused))) -{ -} - -static void test_copy_status(void* to __attribute__((unused)) , - void *from __attribute__((unused))) -{ -} - -static my_bool test_check_status(void* param __attribute__((unused))) -{ - return 0; -} - - -static void *test_thread(void *arg) -{ - int i,j,param=*((int*) arg); - THR_LOCK_DATA data[MAX_LOCK_COUNT]; - THR_LOCK_INFO lock_info; - THR_LOCK_DATA *multi_locks[MAX_LOCK_COUNT]; - my_thread_init(); - - printf("Thread %s (%d) started\n",my_thread_name(),param); fflush(stdout); - - - thr_lock_info_init(&lock_info); - for (i=0; i < lock_counts[param] ; i++) - thr_lock_data_init(locks+tests[param][i].lock_nr,data+i,NULL); - for (j=1 ; j < 10 ; j++) /* try locking 10 times */ - { - for (i=0; i < lock_counts[param] ; i++) - { /* Init multi locks */ - multi_locks[i]= &data[i]; - data[i].type= tests[param][i].lock_type; - } - thr_multi_lock(multi_locks, lock_counts[param], &lock_info, TEST_TIMEOUT); - mysql_mutex_lock(&LOCK_thread_count); - { - int tmp=rand() & 7; /* Do something from 0-2 sec */ - if (tmp == 0) - sleep(1); - else if (tmp == 1) - sleep(2); - else - { - ulong k; - for (k=0 ; k < (ulong) (tmp-2)*100000L ; k++) - sum+=k; - } - } - mysql_mutex_unlock(&LOCK_thread_count); - thr_multi_unlock(multi_locks,lock_counts[param]); - } - - printf("Thread %s (%d) ended\n",my_thread_name(),param); fflush(stdout); - thr_print_locks(); - mysql_mutex_lock(&LOCK_thread_count); - thread_count--; - mysql_cond_signal(&COND_thread_count); /* Tell main we are ready */ - mysql_mutex_unlock(&LOCK_thread_count); - free((uchar*) arg); - return 0; -} - - -int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) -{ - pthread_t tid; - pthread_attr_t thr_attr; - int i,*param,error; - MY_INIT(argv[0]); - if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#') - DBUG_PUSH(argv[1]+2); - - printf("Main thread: %s\n",my_thread_name()); - - if ((error= mysql_cond_init(0, &COND_thread_count, NULL))) - { - fprintf(stderr, "Got error: %d from mysql_cond_init (errno: %d)", - error,errno); - exit(1); - } - if ((error= mysql_mutex_init(0, &LOCK_thread_count, MY_MUTEX_INIT_FAST))) - { - fprintf(stderr, "Got error: %d from mysql_cond_init (errno: %d)", - error,errno); - exit(1); - } - - for (i=0 ; i < (int) array_elements(locks) ; i++) - { - thr_lock_init(locks+i); - locks[i].check_status= test_check_status; - locks[i].update_status=test_update_status; - locks[i].copy_status= test_copy_status; - locks[i].get_status= test_get_status; - } - if ((error=pthread_attr_init(&thr_attr))) - { - fprintf(stderr,"Got error: %d from pthread_attr_init (errno: %d)", - error,errno); - exit(1); - } - if ((error=pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED))) - { - fprintf(stderr, - "Got error: %d from pthread_attr_setdetachstate (errno: %d)", - error,errno); - exit(1); - } -#ifndef pthread_attr_setstacksize /* void return value */ - if ((error=pthread_attr_setstacksize(&thr_attr,65536L))) - { - fprintf(stderr,"Got error: %d from pthread_attr_setstacksize (errno: %d)", - error,errno); - exit(1); - } -#endif -#ifdef HAVE_THR_SETCONCURRENCY - (void) thr_setconcurrency(2); -#endif - for (i=0 ; i < (int) array_elements(lock_counts) ; i++) - { - param=(int*) malloc(sizeof(int)); - *param=i; - - if ((error= mysql_mutex_lock(&LOCK_thread_count))) - { - fprintf(stderr, "Got error: %d from mysql_mutex_lock (errno: %d)", - error, errno); - exit(1); - } - if ((error= mysql_thread_create(0, - &tid, &thr_attr, test_thread, - (void*) param))) - { - fprintf(stderr, "Got error: %d from mysql_thread_create (errno: %d)\n", - error, errno); - mysql_mutex_unlock(&LOCK_thread_count); - exit(1); - } - thread_count++; - mysql_mutex_unlock(&LOCK_thread_count); - } - - pthread_attr_destroy(&thr_attr); - if ((error= mysql_mutex_lock(&LOCK_thread_count))) - fprintf(stderr, "Got error: %d from mysql_mutex_lock\n", error); - while (thread_count) - { - if ((error= mysql_cond_wait(&COND_thread_count, &LOCK_thread_count))) - fprintf(stderr, "Got error: %d from mysql_cond_wait\n", error); - } - if ((error= mysql_mutex_unlock(&LOCK_thread_count))) - fprintf(stderr, "Got error: %d from mysql_mutex_unlock\n", error); - for (i=0 ; i < (int) array_elements(locks) ; i++) - thr_lock_delete(locks+i); -#ifdef EXTRA_DEBUG - if (found_errors) - printf("Got %d warnings\n",found_errors); - else -#endif - printf("Test succeeded\n"); - return 0; -} - -#endif /* MAIN */ diff --git a/dep/mysqllite/mysys/thr_mutex.c b/dep/mysqllite/mysys/thr_mutex.c deleted file mode 100644 index 37ced4f7633..00000000000 --- a/dep/mysqllite/mysys/thr_mutex.c +++ /dev/null @@ -1,503 +0,0 @@ -/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc - - 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 */ - -/* This makes a wrapper for mutex handling to make it easier to debug mutex */ - -#include <my_global.h> -#if defined(TARGET_OS_LINUX) && !defined (__USE_UNIX98) -#define __USE_UNIX98 /* To get rw locks under Linux */ -#endif -#if defined(SAFE_MUTEX) -#undef SAFE_MUTEX /* Avoid safe_mutex redefinitions */ -#include "mysys_priv.h" -#include "my_static.h" -#include <m_string.h> - -#ifndef DO_NOT_REMOVE_THREAD_WRAPPERS -/* Remove wrappers */ -#undef pthread_mutex_t -#undef pthread_mutex_init -#undef pthread_mutex_lock -#undef pthread_mutex_unlock -#undef pthread_mutex_destroy -#undef pthread_cond_wait -#undef pthread_cond_timedwait -#ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT -#define pthread_mutex_init(a,b) my_pthread_mutex_init((a),(b)) -#endif -#endif /* DO_NOT_REMOVE_THREAD_WRAPPERS */ - -/* Not instrumented */ -static pthread_mutex_t THR_LOCK_mutex; -static ulong safe_mutex_count= 0; /* Number of mutexes created */ -#ifdef SAFE_MUTEX_DETECT_DESTROY -static struct st_safe_mutex_info_t *safe_mutex_root= NULL; -#endif - -void safe_mutex_global_init(void) -{ - pthread_mutex_init(&THR_LOCK_mutex,MY_MUTEX_INIT_FAST); -} - - -int safe_mutex_init(safe_mutex_t *mp, - const pthread_mutexattr_t *attr __attribute__((unused)), - const char *file, - uint line) -{ - bzero((char*) mp,sizeof(*mp)); - pthread_mutex_init(&mp->global,MY_MUTEX_INIT_ERRCHK); - pthread_mutex_init(&mp->mutex,attr); - /* Mark that mutex is initialized */ - mp->file= file; - mp->line= line; - -#ifdef SAFE_MUTEX_DETECT_DESTROY - /* - Monitor the freeing of mutexes. This code depends on single thread init - and destroy - */ - if ((mp->info= (safe_mutex_info_t *) malloc(sizeof(safe_mutex_info_t)))) - { - struct st_safe_mutex_info_t *info =mp->info; - - info->init_file= file; - info->init_line= line; - info->prev= NULL; - info->next= NULL; - - pthread_mutex_lock(&THR_LOCK_mutex); - if ((info->next= safe_mutex_root)) - safe_mutex_root->prev= info; - safe_mutex_root= info; - safe_mutex_count++; - pthread_mutex_unlock(&THR_LOCK_mutex); - } -#else - pthread_mutex_lock(&THR_LOCK_mutex); - safe_mutex_count++; - pthread_mutex_unlock(&THR_LOCK_mutex); -#endif /* SAFE_MUTEX_DETECT_DESTROY */ - return 0; -} - - -int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line) -{ - int error; - if (!mp->file) - { - fprintf(stderr, - "safe_mutex: Trying to lock unitialized mutex at %s, line %d\n", - file, line); - fflush(stderr); - abort(); - } - - pthread_mutex_lock(&mp->global); - if (mp->count > 0) - { - if (try_lock) - { - pthread_mutex_unlock(&mp->global); - return EBUSY; - } - else if (pthread_equal(pthread_self(),mp->thread)) - { - fprintf(stderr, - "safe_mutex: Trying to lock mutex at %s, line %d, when the" - " mutex was already locked at %s, line %d in thread %s\n", - file,line,mp->file, mp->line, my_thread_name()); - fflush(stderr); - abort(); - } - } - pthread_mutex_unlock(&mp->global); - - /* - If we are imitating trylock(), we need to take special - precautions. - - - We cannot use pthread_mutex_lock() only since another thread can - overtake this thread and take the lock before this thread - causing pthread_mutex_trylock() to hang. In this case, we should - just return EBUSY. Hence, we use pthread_mutex_trylock() to be - able to return immediately. - - - We cannot just use trylock() and continue execution below, since - this would generate an error and abort execution if the thread - was overtaken and trylock() returned EBUSY . In this case, we - instead just return EBUSY, since this is the expected behaviour - of trylock(). - */ - if (try_lock) - { - error= pthread_mutex_trylock(&mp->mutex); - if (error == EBUSY) - return error; - } - else - error= pthread_mutex_lock(&mp->mutex); - - if (error || (error=pthread_mutex_lock(&mp->global))) - { - fprintf(stderr,"Got error %d when trying to lock mutex at %s, line %d\n", - error, file, line); - fflush(stderr); - abort(); - } - mp->thread= pthread_self(); - if (mp->count++) - { - fprintf(stderr,"safe_mutex: Error in thread libray: Got mutex at %s, \ -line %d more than 1 time\n", file,line); - fflush(stderr); - abort(); - } - mp->file= file; - mp->line=line; - pthread_mutex_unlock(&mp->global); - return error; -} - - -int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line) -{ - int error; - pthread_mutex_lock(&mp->global); - if (mp->count == 0) - { - fprintf(stderr,"safe_mutex: Trying to unlock mutex that wasn't locked at %s, line %d\n Last used at %s, line: %d\n", - file,line,mp->file ? mp->file : "",mp->line); - fflush(stderr); - abort(); - } - if (!pthread_equal(pthread_self(),mp->thread)) - { - fprintf(stderr,"safe_mutex: Trying to unlock mutex at %s, line %d that was locked by another thread at: %s, line: %d\n", - file,line,mp->file,mp->line); - fflush(stderr); - abort(); - } - mp->thread= 0; - mp->count--; -#ifdef __WIN__ - pthread_mutex_unlock(&mp->mutex); - error=0; -#else - error=pthread_mutex_unlock(&mp->mutex); - if (error) - { - fprintf(stderr,"safe_mutex: Got error: %d (%d) when trying to unlock mutex at %s, line %d\n", error, errno, file, line); - fflush(stderr); - abort(); - } -#endif /* __WIN__ */ - pthread_mutex_unlock(&mp->global); - return error; -} - - -int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file, - uint line) -{ - int error; - pthread_mutex_lock(&mp->global); - if (mp->count == 0) - { - fprintf(stderr,"safe_mutex: Trying to cond_wait on a unlocked mutex at %s, line %d\n",file,line); - fflush(stderr); - abort(); - } - if (!pthread_equal(pthread_self(),mp->thread)) - { - fprintf(stderr,"safe_mutex: Trying to cond_wait on a mutex at %s, line %d that was locked by another thread at: %s, line: %d\n", - file,line,mp->file,mp->line); - fflush(stderr); - abort(); - } - - if (mp->count-- != 1) - { - fprintf(stderr,"safe_mutex: Count was %d on locked mutex at %s, line %d\n", - mp->count+1, file, line); - fflush(stderr); - abort(); - } - pthread_mutex_unlock(&mp->global); - error=pthread_cond_wait(cond,&mp->mutex); - pthread_mutex_lock(&mp->global); - if (error) - { - fprintf(stderr,"safe_mutex: Got error: %d (%d) when doing a safe_mutex_wait at %s, line %d\n", error, errno, file, line); - fflush(stderr); - abort(); - } - mp->thread=pthread_self(); - if (mp->count++) - { - fprintf(stderr, - "safe_mutex: Count was %d in thread 0x%lx when locking mutex at %s, line %d\n", - mp->count-1, my_thread_dbug_id(), file, line); - fflush(stderr); - abort(); - } - mp->file= file; - mp->line=line; - pthread_mutex_unlock(&mp->global); - return error; -} - - -int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, - const struct timespec *abstime, - const char *file, uint line) -{ - int error; - pthread_mutex_lock(&mp->global); - if (mp->count != 1 || !pthread_equal(pthread_self(),mp->thread)) - { - fprintf(stderr,"safe_mutex: Trying to cond_wait at %s, line %d on a not hold mutex\n",file,line); - fflush(stderr); - abort(); - } - mp->count--; /* Mutex will be released */ - pthread_mutex_unlock(&mp->global); - error=pthread_cond_timedwait(cond,&mp->mutex,abstime); -#ifdef EXTRA_DEBUG - if (error && (error != EINTR && error != ETIMEDOUT && error != ETIME)) - { - fprintf(stderr,"safe_mutex: Got error: %d (%d) when doing a safe_mutex_timedwait at %s, line %d\n", error, errno, file, line); - } -#endif - pthread_mutex_lock(&mp->global); - mp->thread=pthread_self(); - if (mp->count++) - { - fprintf(stderr, - "safe_mutex: Count was %d in thread 0x%lx when locking mutex at %s, line %d (error: %d (%d))\n", - mp->count-1, my_thread_dbug_id(), file, line, error, error); - fflush(stderr); - abort(); - } - mp->file= file; - mp->line=line; - pthread_mutex_unlock(&mp->global); - return error; -} - - -int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line) -{ - int error=0; - if (!mp->file) - { - fprintf(stderr, - "safe_mutex: Trying to destroy unitialized mutex at %s, line %d\n", - file, line); - fflush(stderr); - abort(); - } - if (mp->count != 0) - { - fprintf(stderr,"safe_mutex: Trying to destroy a mutex that was locked at %s, line %d at %s, line %d\n", - mp->file,mp->line, file, line); - fflush(stderr); - abort(); - } -#ifdef __WIN__ - pthread_mutex_destroy(&mp->global); - pthread_mutex_destroy(&mp->mutex); -#else - if (pthread_mutex_destroy(&mp->global)) - error=1; - if (pthread_mutex_destroy(&mp->mutex)) - error=1; -#endif - mp->file= 0; /* Mark destroyed */ - -#ifdef SAFE_MUTEX_DETECT_DESTROY - if (mp->info) - { - struct st_safe_mutex_info_t *info= mp->info; - pthread_mutex_lock(&THR_LOCK_mutex); - - if (info->prev) - info->prev->next = info->next; - else - safe_mutex_root = info->next; - if (info->next) - info->next->prev = info->prev; - safe_mutex_count--; - - pthread_mutex_unlock(&THR_LOCK_mutex); - free(info); - mp->info= NULL; /* Get crash if double free */ - } -#else - pthread_mutex_lock(&THR_LOCK_mutex); - safe_mutex_count--; - pthread_mutex_unlock(&THR_LOCK_mutex); -#endif /* SAFE_MUTEX_DETECT_DESTROY */ - return error; -} - - -/* - Free global resources and check that all mutex has been destroyed - - SYNOPSIS - safe_mutex_end() - file Print errors on this file - - NOTES - We can't use DBUG_PRINT() here as we have in my_end() disabled - DBUG handling before calling this function. - - In MySQL one may get one warning for a mutex created in my_thr_init.c - This is ok, as this thread may not yet have been exited. -*/ - -void safe_mutex_end(FILE *file __attribute__((unused))) -{ - if (!safe_mutex_count) /* safetly */ - pthread_mutex_destroy(&THR_LOCK_mutex); -#ifdef SAFE_MUTEX_DETECT_DESTROY - if (!file) - return; - - if (safe_mutex_count) - { - fprintf(file, "Warning: Not destroyed mutex: %lu\n", safe_mutex_count); - (void) fflush(file); - } - { - struct st_safe_mutex_info_t *ptr; - for (ptr= safe_mutex_root ; ptr ; ptr= ptr->next) - { - fprintf(file, "\tMutex initiated at line %4u in '%s'\n", - ptr->init_line, ptr->init_file); - (void) fflush(file); - } - } -#endif /* SAFE_MUTEX_DETECT_DESTROY */ -} - -#endif /* SAFE_MUTEX */ - -#if 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 - -static int cpu_count= 0; - -int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, - const pthread_mutexattr_t *attr) -{ - if ((cpu_count > 1) && (attr == MY_MUTEX_INIT_FAST)) - mp->spins= MY_PTHREAD_FASTMUTEX_SPINS; - else - mp->spins= 0; - mp->rng_state= 1; - return pthread_mutex_init(&mp->mutex, attr); -} - -/** - Park-Miller random number generator. A simple linear congruential - generator that operates in multiplicative group of integers modulo n. - - x_{k+1} = (x_k g) mod n - - Popular pair of parameters: n = 2^32 − 5 = 4294967291 and g = 279470273. - The period of the generator is about 2^31. - Largest value that can be returned: 2147483646 (RAND_MAX) - - Reference: - - S. K. Park and K. W. Miller - "Random number generators: good ones are hard to find" - Commun. ACM, October 1988, Volume 31, No 10, pages 1192-1201. -*/ - -static double park_rng(my_pthread_fastmutex_t *mp) -{ - mp->rng_state= ((my_ulonglong)mp->rng_state * 279470273U) % 4294967291U; - return (mp->rng_state / 2147483647.0); -} - -int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp) -{ - int res; - uint i; - uint maxdelay= MY_PTHREAD_FASTMUTEX_DELAY; - - for (i= 0; i < mp->spins; i++) - { - res= pthread_mutex_trylock(&mp->mutex); - - if (res == 0) - return 0; - - if (res != EBUSY) - return res; - - mutex_delay(maxdelay); - maxdelay += park_rng(mp) * MY_PTHREAD_FASTMUTEX_DELAY + 1; - } - return pthread_mutex_lock(&mp->mutex); -} - - -void fastmutex_global_init(void) -{ -#ifdef _SC_NPROCESSORS_CONF - cpu_count= sysconf(_SC_NPROCESSORS_CONF); -#endif -} - -#endif /* defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) */ diff --git a/dep/mysqllite/mysys/thr_rwlock.c b/dep/mysqllite/mysys/thr_rwlock.c deleted file mode 100644 index bad80b43eef..00000000000 --- a/dep/mysqllite/mysys/thr_rwlock.c +++ /dev/null @@ -1,472 +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 */ - -/* Synchronization - readers / writer thread locks */ - -#include "mysys_priv.h" -#if defined(NEED_MY_RW_LOCK) -#include <errno.h> - -#ifdef _WIN32 - -static BOOL have_srwlock= FALSE; -/* Prototypes and function pointers for windows functions */ -typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock); -typedef BOOL (WINAPI* srw_bool_func) (PSRWLOCK SRWLock); - -static srw_func my_InitializeSRWLock; -static srw_func my_AcquireSRWLockExclusive; -static srw_func my_ReleaseSRWLockExclusive; -static srw_func my_AcquireSRWLockShared; -static srw_func my_ReleaseSRWLockShared; - -static srw_bool_func my_TryAcquireSRWLockExclusive; -static srw_bool_func my_TryAcquireSRWLockShared; - -/** - Check for presence of Windows slim reader writer lock function. - Load function pointers. -*/ - -static void check_srwlock_availability(void) -{ - HMODULE module= GetModuleHandle("kernel32"); - - my_InitializeSRWLock= (srw_func) GetProcAddress(module, - "InitializeSRWLock"); - my_AcquireSRWLockExclusive= (srw_func) GetProcAddress(module, - "AcquireSRWLockExclusive"); - my_AcquireSRWLockShared= (srw_func) GetProcAddress(module, - "AcquireSRWLockShared"); - my_ReleaseSRWLockExclusive= (srw_func) GetProcAddress(module, - "ReleaseSRWLockExclusive"); - my_ReleaseSRWLockShared= (srw_func) GetProcAddress(module, - "ReleaseSRWLockShared"); - my_TryAcquireSRWLockExclusive= (srw_bool_func) GetProcAddress(module, - "TryAcquireSRWLockExclusive"); - my_TryAcquireSRWLockShared= (srw_bool_func) GetProcAddress(module, - "TryAcquireSRWLockShared"); - - /* - We currently require TryAcquireSRWLockExclusive. This API is missing on - Vista, this means SRWLock are only used starting with Win7. - - If "trylock" usage for rwlocks is eliminated from server codebase (it is used - in a single place currently, in query cache), then SRWLock can be enabled on - Vista too. In this case condition below needs to be changed to e.g check - for my_InitializeSRWLock. - */ - - if (my_TryAcquireSRWLockExclusive) - have_srwlock= TRUE; - -} - - -static int srw_init(my_rw_lock_t *rwp) -{ - my_InitializeSRWLock(&rwp->srwlock); - rwp->have_exclusive_srwlock = FALSE; - return 0; -} - - -static int srw_rdlock(my_rw_lock_t *rwp) -{ - my_AcquireSRWLockShared(&rwp->srwlock); - return 0; -} - - -static int srw_tryrdlock(my_rw_lock_t *rwp) -{ - - if (!my_TryAcquireSRWLockShared(&rwp->srwlock)) - return EBUSY; - return 0; -} - - -static int srw_wrlock(my_rw_lock_t *rwp) -{ - my_AcquireSRWLockExclusive(&rwp->srwlock); - rwp->have_exclusive_srwlock= TRUE; - return 0; -} - - -static int srw_trywrlock(my_rw_lock_t *rwp) -{ - if (!my_TryAcquireSRWLockExclusive(&rwp->srwlock)) - return EBUSY; - rwp->have_exclusive_srwlock= TRUE; - return 0; -} - - -static int srw_unlock(my_rw_lock_t *rwp) -{ - if (rwp->have_exclusive_srwlock) - { - rwp->have_exclusive_srwlock= FALSE; - my_ReleaseSRWLockExclusive(&rwp->srwlock); - } - else - { - my_ReleaseSRWLockShared(&rwp->srwlock); - } - return 0; -} - -#endif /*_WIN32 */ - -/* - Source base from Sun Microsystems SPILT, simplified for MySQL use - -- Joshua Chamas - Some cleanup and additional code by Monty -*/ - -/* -* Multithreaded Demo Source -* -* Copyright (C) 1995 by Sun Microsystems, Inc. -* All rights reserved. -* -* This file is a product of SunSoft, Inc. and is provided for -* unrestricted use provided that this legend is included on all -* media and as a part of the software program in whole or part. -* Users may copy, modify or distribute this file at will. -* -* THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING -* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR -* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. -* -* This file is provided with no support and without any obligation on the -* part of SunSoft, Inc. to assist in its use, correction, modification or -* enhancement. -* -* SUNSOFT AND SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT -* TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS -* FILE OR ANY PART THEREOF. -* -* IN NO EVENT WILL SUNSOFT OR SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY -* LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL -* DAMAGES, EVEN IF THEY HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH -* DAMAGES. -* -* SunSoft, Inc. -* 2550 Garcia Avenue -* Mountain View, California 94043 -*/ - -int my_rw_init(my_rw_lock_t *rwp) -{ - pthread_condattr_t cond_attr; - -#ifdef _WIN32 - /* - Once initialization is used here rather than in my_init(), in order to - - avoid my_init() pitfalls- (undefined order in which initialization should - run) - - be potentially useful C++ (static constructors) - - just to simplify the API. - Also, the overhead is of my_pthread_once is very small. - */ - static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT; - my_pthread_once(&once_control, check_srwlock_availability); - - if (have_srwlock) - return srw_init(rwp); -#endif - - pthread_mutex_init( &rwp->lock, MY_MUTEX_INIT_FAST); - pthread_condattr_init( &cond_attr ); - pthread_cond_init( &rwp->readers, &cond_attr ); - pthread_cond_init( &rwp->writers, &cond_attr ); - pthread_condattr_destroy(&cond_attr); - - rwp->state = 0; - rwp->waiters = 0; -#ifdef SAFE_MUTEX - rwp->write_thread = 0; -#endif - - return(0); -} - - -int my_rw_destroy(my_rw_lock_t *rwp) -{ -#ifdef _WIN32 - if (have_srwlock) - return 0; /* no destroy function */ -#endif - DBUG_ASSERT(rwp->state == 0); - pthread_mutex_destroy( &rwp->lock ); - pthread_cond_destroy( &rwp->readers ); - pthread_cond_destroy( &rwp->writers ); - return(0); -} - - -int my_rw_rdlock(my_rw_lock_t *rwp) -{ -#ifdef _WIN32 - if (have_srwlock) - return srw_rdlock(rwp); -#endif - - pthread_mutex_lock(&rwp->lock); - - /* active or queued writers */ - while (( rwp->state < 0 ) || rwp->waiters) - pthread_cond_wait( &rwp->readers, &rwp->lock); - - rwp->state++; - pthread_mutex_unlock(&rwp->lock); - return(0); -} - -int my_rw_tryrdlock(my_rw_lock_t *rwp) -{ - int res; - -#ifdef _WIN32 - if (have_srwlock) - return srw_tryrdlock(rwp); -#endif - - pthread_mutex_lock(&rwp->lock); - if ((rwp->state < 0 ) || rwp->waiters) - res= EBUSY; /* Can't get lock */ - else - { - res=0; - rwp->state++; - } - pthread_mutex_unlock(&rwp->lock); - return(res); -} - - -int my_rw_wrlock(my_rw_lock_t *rwp) -{ -#ifdef _WIN32 - if (have_srwlock) - return srw_wrlock(rwp); -#endif - - pthread_mutex_lock(&rwp->lock); - rwp->waiters++; /* another writer queued */ - - my_rw_lock_assert_not_write_owner(rwp); - - while (rwp->state) - pthread_cond_wait(&rwp->writers, &rwp->lock); - rwp->state = -1; - rwp->waiters--; -#ifdef SAFE_MUTEX - rwp->write_thread= pthread_self(); -#endif - pthread_mutex_unlock(&rwp->lock); - return(0); -} - - -int my_rw_trywrlock(my_rw_lock_t *rwp) -{ - int res; - -#ifdef _WIN32 - if (have_srwlock) - return srw_trywrlock(rwp); -#endif - - pthread_mutex_lock(&rwp->lock); - if (rwp->state) - res= EBUSY; /* Can't get lock */ - else - { - res=0; - rwp->state = -1; -#ifdef SAFE_MUTEX - rwp->write_thread= pthread_self(); -#endif - } - pthread_mutex_unlock(&rwp->lock); - return(res); -} - - -int my_rw_unlock(my_rw_lock_t *rwp) -{ -#ifdef _WIN32 - if (have_srwlock) - return srw_unlock(rwp); -#endif - - DBUG_PRINT("rw_unlock", - ("state: %d waiters: %d", rwp->state, rwp->waiters)); - pthread_mutex_lock(&rwp->lock); - - DBUG_ASSERT(rwp->state != 0); - - if (rwp->state == -1) /* writer releasing */ - { - my_rw_lock_assert_write_owner(rwp); - rwp->state= 0; /* mark as available */ -#ifdef SAFE_MUTEX - rwp->write_thread= 0; -#endif - - if ( rwp->waiters ) /* writers queued */ - pthread_cond_signal( &rwp->writers ); - else - pthread_cond_broadcast( &rwp->readers ); - } - else - { - if ( --rwp->state == 0 && /* no more readers */ - rwp->waiters) - pthread_cond_signal( &rwp->writers ); - } - - pthread_mutex_unlock( &rwp->lock ); - return(0); -} - -#endif /* defined(NEED_MY_RW_LOCK) */ - - -int rw_pr_init(rw_pr_lock_t *rwlock) -{ - pthread_mutex_init(&rwlock->lock, NULL); - pthread_cond_init(&rwlock->no_active_readers, NULL); - rwlock->active_readers= 0; - rwlock->writers_waiting_readers= 0; - rwlock->active_writer= FALSE; -#ifdef SAFE_MUTEX - rwlock->writer_thread= 0; -#endif - return 0; -} - - -int rw_pr_destroy(rw_pr_lock_t *rwlock) -{ - pthread_cond_destroy(&rwlock->no_active_readers); - pthread_mutex_destroy(&rwlock->lock); - return 0; -} - - -int rw_pr_rdlock(rw_pr_lock_t *rwlock) -{ - pthread_mutex_lock(&rwlock->lock); - /* - The fact that we were able to acquire 'lock' mutex means - that there are no active writers and we can acquire rd-lock. - Increment active readers counter to prevent requests for - wr-lock from succeeding and unlock mutex. - */ - rwlock->active_readers++; - pthread_mutex_unlock(&rwlock->lock); - return 0; -} - - -int rw_pr_wrlock(rw_pr_lock_t *rwlock) -{ - pthread_mutex_lock(&rwlock->lock); - - if (rwlock->active_readers != 0) - { - /* There are active readers. We have to wait until they are gone. */ - rwlock->writers_waiting_readers++; - - while (rwlock->active_readers != 0) - pthread_cond_wait(&rwlock->no_active_readers, &rwlock->lock); - - rwlock->writers_waiting_readers--; - } - - /* - We own 'lock' mutex so there is no active writers. - Also there are no active readers. - This means that we can grant wr-lock. - Not releasing 'lock' mutex until unlock will block - both requests for rd and wr-locks. - Set 'active_writer' flag to simplify unlock. - - Thanks to the fact wr-lock/unlock in the absence of - contention from readers is essentially mutex lock/unlock - with a few simple checks make this rwlock implementation - wr-lock optimized. - */ - rwlock->active_writer= TRUE; -#ifdef SAFE_MUTEX - rwlock->writer_thread= pthread_self(); -#endif - return 0; -} - - -int rw_pr_unlock(rw_pr_lock_t *rwlock) -{ - if (rwlock->active_writer) - { - /* We are unlocking wr-lock. */ -#ifdef SAFE_MUTEX - rwlock->writer_thread= 0; -#endif - rwlock->active_writer= FALSE; - if (rwlock->writers_waiting_readers) - { - /* - Avoid expensive cond signal in case when there is no contention - or it is wr-only. - - Note that from view point of performance it would be better to - signal on the condition variable after unlocking mutex (as it - reduces number of contex switches). - - Unfortunately this would mean that such rwlock can't be safely - used by MDL subsystem, which relies on the fact that it is OK - to destroy rwlock once it is in unlocked state. - */ - pthread_cond_signal(&rwlock->no_active_readers); - } - pthread_mutex_unlock(&rwlock->lock); - } - else - { - /* We are unlocking rd-lock. */ - pthread_mutex_lock(&rwlock->lock); - rwlock->active_readers--; - if (rwlock->active_readers == 0 && - rwlock->writers_waiting_readers) - { - /* - If we are last reader and there are waiting - writers wake them up. - */ - pthread_cond_signal(&rwlock->no_active_readers); - } - pthread_mutex_unlock(&rwlock->lock); - } - return 0; -} - - diff --git a/dep/mysqllite/mysys/tree.c b/dep/mysqllite/mysys/tree.c deleted file mode 100644 index 8ea7102ed4c..00000000000 --- a/dep/mysqllite/mysys/tree.c +++ /dev/null @@ -1,757 +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 */ - -/* - Code for handling red-black (balanced) binary trees. - key in tree is allocated accrding to following: - - 1) If size < 0 then tree will not allocate keys and only a pointer to - each key is saved in tree. - compare and search functions uses and returns key-pointer - - 2) If size == 0 then there are two options: - - key_size != 0 to tree_insert: The key will be stored in the tree. - - key_size == 0 to tree_insert: A pointer to the key is stored. - compare and search functions uses and returns key-pointer. - - 3) if key_size is given to init_tree then each node will continue the - key and calls to insert_key may increase length of key. - if key_size > sizeof(pointer) and key_size is a multiple of 8 (double - allign) then key will be put on a 8 alligned adress. Else - the key will be on adress (element+1). This is transparent for user - compare and search functions uses a pointer to given key-argument. - - - If you use a free function for tree-elements and you are freeing - the element itself, you should use key_size = 0 to init_tree and - tree_search - - The actual key in TREE_ELEMENT is saved as a pointer or after the - TREE_ELEMENT struct. - If one uses only pointers in tree one can use tree_set_pointer() to - change address of data. - - Implemented by monty. -*/ - -/* - NOTE: - tree->compare function should be ALWAYS called as - (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), key) - and not other way around, as - (*tree->compare)(custom_arg, key, ELEMENT_KEY(tree,element)) - - ft_boolean_search.c (at least) relies on that. -*/ - -#include "mysys_priv.h" -#include <m_string.h> -#include <my_tree.h> -#include "my_base.h" - -#define BLACK 1 -#define RED 0 -#define DEFAULT_ALLOC_SIZE 8192 -#define DEFAULT_ALIGN_SIZE 8192 - -static void delete_tree_element(TREE *,TREE_ELEMENT *); -static int tree_walk_left_root_right(TREE *,TREE_ELEMENT *, - tree_walk_action,void *); -static int tree_walk_right_root_left(TREE *,TREE_ELEMENT *, - tree_walk_action,void *); -static void left_rotate(TREE_ELEMENT **parent,TREE_ELEMENT *leaf); -static void right_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf); -static void rb_insert(TREE *tree,TREE_ELEMENT ***parent, - TREE_ELEMENT *leaf); -static void rb_delete_fixup(TREE *tree,TREE_ELEMENT ***parent); - - - /* The actuall code for handling binary trees */ - -#ifndef DBUG_OFF -static int test_rb_tree(TREE_ELEMENT *element); -#endif - -void init_tree(TREE *tree, ulong default_alloc_size, ulong memory_limit, - int size, qsort_cmp2 compare, my_bool with_delete, - tree_element_free free_element, void *custom_arg) -{ - DBUG_ENTER("init_tree"); - DBUG_PRINT("enter",("tree: 0x%lx size: %d", (long) tree, size)); - - if (default_alloc_size < DEFAULT_ALLOC_SIZE) - default_alloc_size= DEFAULT_ALLOC_SIZE; - default_alloc_size= MY_ALIGN(default_alloc_size, DEFAULT_ALIGN_SIZE); - bzero((uchar*) &tree->null_element,sizeof(tree->null_element)); - tree->root= &tree->null_element; - tree->compare=compare; - tree->size_of_element=size > 0 ? (uint) size : 0; - tree->memory_limit=memory_limit; - tree->free=free_element; - tree->allocated=0; - tree->elements_in_tree=0; - tree->custom_arg = custom_arg; - tree->null_element.colour=BLACK; - tree->null_element.left=tree->null_element.right=0; - tree->flag= 0; - if (!free_element && size >= 0 && - ((uint) size <= sizeof(void*) || ((uint) size & (sizeof(void*)-1)))) - { - /* - We know that the data doesn't have to be aligned (like if the key - contains a double), so we can store the data combined with the - TREE_ELEMENT. - */ - tree->offset_to_key=sizeof(TREE_ELEMENT); /* Put key after element */ - /* Fix allocation size so that we don't lose any memory */ - default_alloc_size/=(sizeof(TREE_ELEMENT)+size); - if (!default_alloc_size) - default_alloc_size=1; - default_alloc_size*=(sizeof(TREE_ELEMENT)+size); - } - else - { - tree->offset_to_key=0; /* use key through pointer */ - tree->size_of_element+=sizeof(void*); - } - if (!(tree->with_delete=with_delete)) - { - init_alloc_root(&tree->mem_root, (uint) default_alloc_size, 0); - tree->mem_root.min_malloc=(sizeof(TREE_ELEMENT)+tree->size_of_element); - } - DBUG_VOID_RETURN; -} - -static void free_tree(TREE *tree, myf free_flags) -{ - DBUG_ENTER("free_tree"); - DBUG_PRINT("enter",("tree: 0x%lx", (long) tree)); - - if (tree->root) /* If initialized */ - { - if (tree->with_delete) - delete_tree_element(tree,tree->root); - else - { - if (tree->free) - { - if (tree->memory_limit) - (*tree->free)(NULL, free_init, tree->custom_arg); - delete_tree_element(tree,tree->root); - if (tree->memory_limit) - (*tree->free)(NULL, free_end, tree->custom_arg); - } - free_root(&tree->mem_root, free_flags); - } - } - tree->root= &tree->null_element; - tree->elements_in_tree=0; - tree->allocated=0; - - DBUG_VOID_RETURN; -} - -void delete_tree(TREE* tree) -{ - free_tree(tree, MYF(0)); /* my_free() mem_root if applicable */ -} - -void reset_tree(TREE* tree) -{ - /* do not free mem_root, just mark blocks as free */ - free_tree(tree, MYF(MY_MARK_BLOCKS_FREE)); -} - - -static void delete_tree_element(TREE *tree, TREE_ELEMENT *element) -{ - if (element != &tree->null_element) - { - delete_tree_element(tree,element->left); - if (tree->free) - (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); - delete_tree_element(tree,element->right); - if (tree->with_delete) - my_free(element); - } -} - - -/* - insert, search and delete of elements - - The following should be true: - parent[0] = & parent[-1][0]->left || - parent[0] = & parent[-1][0]->right -*/ - -TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, - void* custom_arg) -{ - int cmp; - TREE_ELEMENT *element,***parent; - - parent= tree->parents; - *parent = &tree->root; element= tree->root; - for (;;) - { - if (element == &tree->null_element || - (cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), - key)) == 0) - break; - if (cmp < 0) - { - *++parent= &element->right; element= element->right; - } - else - { - *++parent = &element->left; element= element->left; - } - } - if (element == &tree->null_element) - { - uint alloc_size=sizeof(TREE_ELEMENT)+key_size+tree->size_of_element; - tree->allocated+=alloc_size; - - if (tree->memory_limit && tree->elements_in_tree - && tree->allocated > tree->memory_limit) - { - reset_tree(tree); - return tree_insert(tree, key, key_size, custom_arg); - } - - key_size+=tree->size_of_element; - if (tree->with_delete) - element=(TREE_ELEMENT *) my_malloc(alloc_size, MYF(MY_WME)); - else - element=(TREE_ELEMENT *) alloc_root(&tree->mem_root,alloc_size); - if (!element) - return(NULL); - **parent=element; - element->left=element->right= &tree->null_element; - if (!tree->offset_to_key) - { - if (key_size == sizeof(void*)) /* no length, save pointer */ - *((void**) (element+1))=key; - else - { - *((void**) (element+1))= (void*) ((void **) (element+1)+1); - memcpy((uchar*) *((void **) (element+1)),key, - (size_t) (key_size-sizeof(void*))); - } - } - else - memcpy((uchar*) element+tree->offset_to_key,key,(size_t) key_size); - element->count=1; /* May give warning in purify */ - tree->elements_in_tree++; - rb_insert(tree,parent,element); /* rebalance tree */ - } - else - { - if (tree->flag & TREE_NO_DUPS) - return(NULL); - element->count++; - /* Avoid a wrap over of the count. */ - if (! element->count) - element->count--; - } - DBUG_EXECUTE("check_tree", test_rb_tree(tree->root);); - return element; -} - -int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg) -{ - int cmp,remove_colour; - TREE_ELEMENT *element,***parent, ***org_parent, *nod; - if (!tree->with_delete) - return 1; /* not allowed */ - - parent= tree->parents; - *parent= &tree->root; element= tree->root; - for (;;) - { - if (element == &tree->null_element) - return 1; /* Was not in tree */ - if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), - key)) == 0) - break; - if (cmp < 0) - { - *++parent= &element->right; element= element->right; - } - else - { - *++parent = &element->left; element= element->left; - } - } - if (element->left == &tree->null_element) - { - (**parent)=element->right; - remove_colour= element->colour; - } - else if (element->right == &tree->null_element) - { - (**parent)=element->left; - remove_colour= element->colour; - } - else - { - org_parent= parent; - *++parent= &element->right; nod= element->right; - while (nod->left != &tree->null_element) - { - *++parent= &nod->left; nod= nod->left; - } - (**parent)=nod->right; /* unlink nod from tree */ - remove_colour= nod->colour; - org_parent[0][0]=nod; /* put y in place of element */ - org_parent[1]= &nod->right; - nod->left=element->left; - nod->right=element->right; - nod->colour=element->colour; - } - if (remove_colour == BLACK) - rb_delete_fixup(tree,parent); - if (tree->free) - (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); - tree->allocated-= sizeof(TREE_ELEMENT) + tree->size_of_element + key_size; - my_free(element); - tree->elements_in_tree--; - return 0; -} - - -void *tree_search(TREE *tree, void *key, void *custom_arg) -{ - int cmp; - TREE_ELEMENT *element=tree->root; - - for (;;) - { - if (element == &tree->null_element) - return (void*) 0; - if ((cmp = (*tree->compare)(custom_arg, ELEMENT_KEY(tree,element), - key)) == 0) - return ELEMENT_KEY(tree,element); - if (cmp < 0) - element=element->right; - else - element=element->left; - } -} - -void *tree_search_key(TREE *tree, const void *key, - TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, - enum ha_rkey_function flag, void *custom_arg) -{ - int cmp; - TREE_ELEMENT *element= tree->root; - TREE_ELEMENT **last_left_step_parent= NULL, **last_right_step_parent= NULL; - TREE_ELEMENT **last_equal_element= NULL; - -/* - TODO: support for HA_READ_KEY_OR_PREV, HA_READ_PREFIX flags if needed. -*/ - - *parents = &tree->null_element; - while (element != &tree->null_element) - { - *++parents= element; - if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element), - key)) == 0) - { - switch (flag) { - case HA_READ_KEY_EXACT: - case HA_READ_KEY_OR_NEXT: - case HA_READ_BEFORE_KEY: - last_equal_element= parents; - cmp= 1; - break; - case HA_READ_AFTER_KEY: - cmp= -1; - break; - case HA_READ_PREFIX_LAST: - case HA_READ_PREFIX_LAST_OR_PREV: - last_equal_element= parents; - cmp= -1; - break; - default: - return NULL; - } - } - if (cmp < 0) /* element < key */ - { - last_right_step_parent= parents; - element= element->right; - } - else - { - last_left_step_parent= parents; - element= element->left; - } - } - switch (flag) { - case HA_READ_KEY_EXACT: - case HA_READ_PREFIX_LAST: - *last_pos= last_equal_element; - break; - case HA_READ_KEY_OR_NEXT: - *last_pos= last_equal_element ? last_equal_element : last_left_step_parent; - break; - case HA_READ_AFTER_KEY: - *last_pos= last_left_step_parent; - break; - case HA_READ_PREFIX_LAST_OR_PREV: - *last_pos= last_equal_element ? last_equal_element : last_right_step_parent; - break; - case HA_READ_BEFORE_KEY: - *last_pos= last_right_step_parent; - break; - default: - return NULL; - } - return *last_pos ? ELEMENT_KEY(tree, **last_pos) : NULL; -} - -/* - Search first (the most left) or last (the most right) tree element -*/ -void *tree_search_edge(TREE *tree, TREE_ELEMENT **parents, - TREE_ELEMENT ***last_pos, int child_offs) -{ - TREE_ELEMENT *element= tree->root; - - *parents= &tree->null_element; - while (element != &tree->null_element) - { - *++parents= element; - element= ELEMENT_CHILD(element, child_offs); - } - *last_pos= parents; - return **last_pos != &tree->null_element ? - ELEMENT_KEY(tree, **last_pos) : NULL; -} - -void *tree_search_next(TREE *tree, TREE_ELEMENT ***last_pos, int l_offs, - int r_offs) -{ - TREE_ELEMENT *x= **last_pos; - - if (ELEMENT_CHILD(x, r_offs) != &tree->null_element) - { - x= ELEMENT_CHILD(x, r_offs); - *++*last_pos= x; - while (ELEMENT_CHILD(x, l_offs) != &tree->null_element) - { - x= ELEMENT_CHILD(x, l_offs); - *++*last_pos= x; - } - return ELEMENT_KEY(tree, x); - } - else - { - TREE_ELEMENT *y= *--*last_pos; - while (y != &tree->null_element && x == ELEMENT_CHILD(y, r_offs)) - { - x= y; - y= *--*last_pos; - } - return y == &tree->null_element ? NULL : ELEMENT_KEY(tree, y); - } -} - -/* - Expected that tree is fully balanced - (each path from root to leaf has the same length) -*/ -ha_rows tree_record_pos(TREE *tree, const void *key, - enum ha_rkey_function flag, void *custom_arg) -{ - int cmp; - TREE_ELEMENT *element= tree->root; - double left= 1; - double right= tree->elements_in_tree; - - while (element != &tree->null_element) - { - if ((cmp= (*tree->compare)(custom_arg, ELEMENT_KEY(tree, element), - key)) == 0) - { - switch (flag) { - case HA_READ_KEY_EXACT: - case HA_READ_BEFORE_KEY: - cmp= 1; - break; - case HA_READ_AFTER_KEY: - cmp= -1; - break; - default: - return HA_POS_ERROR; - } - } - if (cmp < 0) /* element < key */ - { - element= element->right; - left= (left + right) / 2; - } - else - { - element= element->left; - right= (left + right) / 2; - } - } - switch (flag) { - case HA_READ_KEY_EXACT: - case HA_READ_BEFORE_KEY: - return (ha_rows) right; - case HA_READ_AFTER_KEY: - return (ha_rows) left; - default: - return HA_POS_ERROR; - } -} - -int tree_walk(TREE *tree, tree_walk_action action, void *argument, TREE_WALK visit) -{ - switch (visit) { - case left_root_right: - return tree_walk_left_root_right(tree,tree->root,action,argument); - case right_root_left: - return tree_walk_right_root_left(tree,tree->root,action,argument); - } - return 0; /* Keep gcc happy */ -} - -static int tree_walk_left_root_right(TREE *tree, TREE_ELEMENT *element, tree_walk_action action, void *argument) -{ - int error; - if (element->left) /* Not null_element */ - { - if ((error=tree_walk_left_root_right(tree,element->left,action, - argument)) == 0 && - (error=(*action)(ELEMENT_KEY(tree,element), - (element_count) element->count, - argument)) == 0) - error=tree_walk_left_root_right(tree,element->right,action,argument); - return error; - } - return 0; -} - -static int tree_walk_right_root_left(TREE *tree, TREE_ELEMENT *element, tree_walk_action action, void *argument) -{ - int error; - if (element->right) /* Not null_element */ - { - if ((error=tree_walk_right_root_left(tree,element->right,action, - argument)) == 0 && - (error=(*action)(ELEMENT_KEY(tree,element), - (element_count) element->count, - argument)) == 0) - error=tree_walk_right_root_left(tree,element->left,action,argument); - return error; - } - return 0; -} - - - /* Functions to fix up the tree after insert and delete */ - -static void left_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf) -{ - TREE_ELEMENT *y; - - y=leaf->right; - leaf->right=y->left; - parent[0]=y; - y->left=leaf; -} - -static void right_rotate(TREE_ELEMENT **parent, TREE_ELEMENT *leaf) -{ - TREE_ELEMENT *x; - - x=leaf->left; - leaf->left=x->right; - parent[0]=x; - x->right=leaf; -} - -static void rb_insert(TREE *tree, TREE_ELEMENT ***parent, TREE_ELEMENT *leaf) -{ - TREE_ELEMENT *y,*par,*par2; - - leaf->colour=RED; - while (leaf != tree->root && (par=parent[-1][0])->colour == RED) - { - if (par == (par2=parent[-2][0])->left) - { - y= par2->right; - if (y->colour == RED) - { - par->colour=BLACK; - y->colour=BLACK; - leaf=par2; - parent-=2; - leaf->colour=RED; /* And the loop continues */ - } - else - { - if (leaf == par->right) - { - left_rotate(parent[-1],par); - par=leaf; /* leaf is now parent to old leaf */ - } - par->colour=BLACK; - par2->colour=RED; - right_rotate(parent[-2],par2); - break; - } - } - else - { - y= par2->left; - if (y->colour == RED) - { - par->colour=BLACK; - y->colour=BLACK; - leaf=par2; - parent-=2; - leaf->colour=RED; /* And the loop continues */ - } - else - { - if (leaf == par->left) - { - right_rotate(parent[-1],par); - par=leaf; - } - par->colour=BLACK; - par2->colour=RED; - left_rotate(parent[-2],par2); - break; - } - } - } - tree->root->colour=BLACK; -} - -static void rb_delete_fixup(TREE *tree, TREE_ELEMENT ***parent) -{ - TREE_ELEMENT *x,*w,*par; - - x= **parent; - while (x != tree->root && x->colour == BLACK) - { - if (x == (par=parent[-1][0])->left) - { - w=par->right; - if (w->colour == RED) - { - w->colour=BLACK; - par->colour=RED; - left_rotate(parent[-1],par); - parent[0]= &w->left; - *++parent= &par->left; - w=par->right; - } - if (w->left->colour == BLACK && w->right->colour == BLACK) - { - w->colour=RED; - x=par; - parent--; - } - else - { - if (w->right->colour == BLACK) - { - w->left->colour=BLACK; - w->colour=RED; - right_rotate(&par->right,w); - w=par->right; - } - w->colour=par->colour; - par->colour=BLACK; - w->right->colour=BLACK; - left_rotate(parent[-1],par); - x=tree->root; - break; - } - } - else - { - w=par->left; - if (w->colour == RED) - { - w->colour=BLACK; - par->colour=RED; - right_rotate(parent[-1],par); - parent[0]= &w->right; - *++parent= &par->right; - w=par->left; - } - if (w->right->colour == BLACK && w->left->colour == BLACK) - { - w->colour=RED; - x=par; - parent--; - } - else - { - if (w->left->colour == BLACK) - { - w->right->colour=BLACK; - w->colour=RED; - left_rotate(&par->left,w); - w=par->left; - } - w->colour=par->colour; - par->colour=BLACK; - w->left->colour=BLACK; - right_rotate(parent[-1],par); - x=tree->root; - break; - } - } - } - x->colour=BLACK; -} - -#ifndef DBUG_OFF - - /* Test that the proporties for a red-black tree holds */ - -static int test_rb_tree(TREE_ELEMENT *element) -{ - int count_l,count_r; - - if (!element->left) - return 0; /* Found end of tree */ - if (element->colour == RED && - (element->left->colour == RED || element->right->colour == RED)) - { - printf("Wrong tree: Found two red in a row\n"); - return -1; - } - count_l=test_rb_tree(element->left); - count_r=test_rb_tree(element->right); - if (count_l >= 0 && count_r >= 0) - { - if (count_l == count_r) - return count_l+(element->colour == BLACK); - printf("Wrong tree: Incorrect black-count: %d - %d\n",count_l,count_r); - } - return -1; -} -#endif diff --git a/dep/mysqllite/mysys/typelib.c b/dep/mysqllite/mysys/typelib.c deleted file mode 100644 index 7681ff581ac..00000000000 --- a/dep/mysqllite/mysys/typelib.c +++ /dev/null @@ -1,388 +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 */ - -/* Functions to handle typelib */ - -#include "mysys_priv.h" -#include <m_string.h> -#include <m_ctype.h> - - -#define is_field_separator(X) ((X) == ',' || (X) == '=') - -int find_type_or_exit(const char *x, TYPELIB *typelib, const char *option) -{ - int res; - const char **ptr; - - if ((res= find_type((char *) x, typelib, 2)) <= 0) - { - ptr= typelib->type_names; - if (!*x) - fprintf(stderr, "No option given to %s\n", option); - else - fprintf(stderr, "Unknown option to %s: %s\n", option, x); - fprintf(stderr, "Alternatives are: '%s'", *ptr); - while (*++ptr) - fprintf(stderr, ",'%s'", *ptr); - fprintf(stderr, "\n"); - exit(1); - } - return res; -} - - -/** - Search after a string in a list of strings. Endspace in x is not compared. - - @param x String to find - @param lib TYPELIB (struct of pointer to values + count) - @param full_name bitmap of what to do - If & 1 accept only whole names - If & 2 don't expand if half field - If & 4 allow #number# as type - If & 8 use ',' as string terminator - - @note - If part, uniq field is found and full_name == 0 then x is expanded - to full field. - - @retval - -1 Too many matching values - @retval - 0 No matching value - @retval - >0 Offset+1 in typelib for matched string -*/ - - -int find_type(char *x, const TYPELIB *typelib, uint full_name) -{ - int find,pos; - int UNINIT_VAR(findpos); /* guarded by find */ - reg1 char * i; - reg2 const char *j; - DBUG_ENTER("find_type"); - DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) typelib)); - - if (!typelib->count) - { - DBUG_PRINT("exit",("no count")); - DBUG_RETURN(0); - } - find=0; - for (pos=0 ; (j=typelib->type_names[pos]) ; pos++) - { - for (i=x ; - *i && (!(full_name & 8) || !is_field_separator(*i)) && - my_toupper(&my_charset_latin1,*i) == - my_toupper(&my_charset_latin1,*j) ; i++, j++) ; - if (! *j) - { - while (*i == ' ') - i++; /* skip_end_space */ - if (! *i || ((full_name & 8) && is_field_separator(*i))) - DBUG_RETURN(pos+1); - } - if ((!*i && (!(full_name & 8) || !is_field_separator(*i))) && - (!*j || !(full_name & 1))) - { - find++; - findpos=pos; - } - } - if (find == 0 && (full_name & 4) && x[0] == '#' && strend(x)[-1] == '#' && - (findpos=atoi(x+1)-1) >= 0 && (uint) findpos < typelib->count) - find=1; - else if (find == 0 || ! x[0]) - { - DBUG_PRINT("exit",("Couldn't find type")); - DBUG_RETURN(0); - } - else if (find != 1 || (full_name & 1)) - { - DBUG_PRINT("exit",("Too many possybilities")); - DBUG_RETURN(-1); - } - if (!(full_name & 2)) - (void) strmov(x,typelib->type_names[findpos]); - DBUG_RETURN(findpos+1); -} /* find_type */ - - -/** - Get name of type nr - - @note - first type is 1, 0 = empty field -*/ - -void make_type(register char * to, register uint nr, - register TYPELIB *typelib) -{ - DBUG_ENTER("make_type"); - if (!nr) - to[0]=0; - else - (void) strmov(to,get_type(typelib,nr-1)); - DBUG_VOID_RETURN; -} /* make_type */ - - -/** - Get type - - @note - first type is 0 -*/ - -const char *get_type(TYPELIB *typelib, uint nr) -{ - if (nr < (uint) typelib->count && typelib->type_names) - return(typelib->type_names[nr]); - return "?"; -} - - -/** - Create an integer value to represent the supplied comma-seperated - string where each string in the TYPELIB denotes a bit position. - - @param x string to decompose - @param lib TYPELIB (struct of pointer to values + count) - @param err index (not char position) of string element which was not - found or 0 if there was no error - - @retval - a integer representation of the supplied string -*/ - -my_ulonglong find_typeset(char *x, TYPELIB *lib, int *err) -{ - my_ulonglong result; - int find; - char *i; - DBUG_ENTER("find_set"); - DBUG_PRINT("enter",("x: '%s' lib: 0x%lx", x, (long) lib)); - - if (!lib->count) - { - DBUG_PRINT("exit",("no count")); - DBUG_RETURN(0); - } - result= 0; - *err= 0; - while (*x) - { - (*err)++; - i= x; - while (*x && !is_field_separator(*x)) - x++; - if (x[0] && x[1]) /* skip separator if found */ - x++; - if ((find= find_type(i, lib, 2 | 8) - 1) < 0) - DBUG_RETURN(0); - result|= (ULL(1) << find); - } - *err= 0; - DBUG_RETURN(result); -} /* find_set */ - - -/** - Create a copy of a specified TYPELIB structure. - - @param root pointer to a MEM_ROOT object for allocations - @param from pointer to a source TYPELIB structure - - @retval - pointer to the new TYPELIB structure on successful copy - @retval - NULL otherwise -*/ - -TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from) -{ - TYPELIB *to; - uint i; - - if (!from) - return NULL; - - if (!(to= (TYPELIB*) alloc_root(root, sizeof(TYPELIB)))) - return NULL; - - if (!(to->type_names= (const char **) - alloc_root(root, (sizeof(char *) + sizeof(int)) * (from->count + 1)))) - return NULL; - to->type_lengths= (unsigned int *)(to->type_names + from->count + 1); - to->count= from->count; - if (from->name) - { - if (!(to->name= strdup_root(root, from->name))) - return NULL; - } - else - to->name= NULL; - - for (i= 0; i < from->count; i++) - { - if (!(to->type_names[i]= strmake_root(root, from->type_names[i], - from->type_lengths[i]))) - return NULL; - to->type_lengths[i]= from->type_lengths[i]; - } - to->type_names[to->count]= NULL; - to->type_lengths[to->count]= 0; - - return to; -} - - -static const char *on_off_default_names[]= { "off","on","default", 0}; -static TYPELIB on_off_default_typelib= {array_elements(on_off_default_names)-1, - "", on_off_default_names, 0}; - -/** - Parse a TYPELIB name from the buffer - - @param lib Set of names to scan for. - @param strpos INOUT Start of the buffer (updated to point to the next - character after the name) - @param end End of the buffer - - @note - The buffer is assumed to contain one of the names specified in the TYPELIB, - followed by comma, '=', or end of the buffer. - - @retval - 0 No matching name - @retval - >0 Offset+1 in typelib for matched name -*/ - -static uint parse_name(const TYPELIB *lib, const char **strpos, const char *end) -{ - const char *pos= *strpos; - uint find= find_type((char*)pos, lib, 8); - for (; pos != end && *pos != '=' && *pos !=',' ; pos++); - *strpos= pos; - return find; -} - -/** - Parse and apply a set of flag assingments - - @param lib Flag names - @param default_name Number of "default" in the typelib - @param cur_set Current set of flags (start from this state) - @param default_set Default set of flags (use this for assign-default - keyword and flag=default assignments) - @param str String to be parsed - @param length Length of the string - @param err_pos OUT If error, set to point to start of wrong set string - NULL on success - @param err_len OUT If error, set to the length of wrong set string - - @details - Parse a set of flag assignments, that is, parse a string in form: - - param_name1=value1,param_name2=value2,... - - where the names are specified in the TYPELIB, and each value can be - either 'on','off', or 'default'. Setting the same name twice is not - allowed. - - Besides param=val assignments, we support the "default" keyword (keyword - #default_name in the typelib). It can be used one time, if specified it - causes us to build the new set over the default_set rather than cur_set - value. - - @note - it's not charset aware - - @retval - Parsed set value if (*errpos == NULL), otherwise undefined -*/ - -my_ulonglong find_set_from_flags(const TYPELIB *lib, uint default_name, - my_ulonglong cur_set, my_ulonglong default_set, - const char *str, uint length, - char **err_pos, uint *err_len) -{ - const char *end= str + length; - my_ulonglong flags_to_set= 0, flags_to_clear= 0, res; - my_bool set_defaults= 0; - - *err_pos= 0; /* No error yet */ - if (str != end) - { - const char *start= str; - for (;;) - { - const char *pos= start; - uint flag_no, value; - - if (!(flag_no= parse_name(lib, &pos, end))) - goto err; - - if (flag_no == default_name) - { - /* Using 'default' twice isn't allowed. */ - if (set_defaults) - goto err; - set_defaults= TRUE; - } - else - { - my_ulonglong bit= (1ULL << (flag_no - 1)); - /* parse the '=on|off|default' */ - if ((flags_to_clear | flags_to_set) & bit || - pos >= end || *pos++ != '=' || - !(value= parse_name(&on_off_default_typelib, &pos, end))) - goto err; - - if (value == 1) /* this is '=off' */ - flags_to_clear|= bit; - else if (value == 2) /* this is '=on' */ - flags_to_set|= bit; - else /* this is '=default' */ - { - if (default_set & bit) - flags_to_set|= bit; - else - flags_to_clear|= bit; - } - } - if (pos >= end) - break; - - if (*pos++ != ',') - goto err; - - start=pos; - continue; - err: - *err_pos= (char*)start; - *err_len= end - start; - break; - } - } - res= set_defaults? default_set : cur_set; - res|= flags_to_set; - res&= ~flags_to_clear; - return res; -} - |
