summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rw-r--r--mysys/array.c90
-rw-r--r--mysys/mf_iocache.c1
-rw-r--r--mysys/mf_keycache.c27
-rw-r--r--mysys/mf_tempfile.c1
-rw-r--r--mysys/my_atomic.c9
-rw-r--r--mysys/my_bit.c100
-rw-r--r--mysys/my_bitmap.c1
-rw-r--r--mysys/my_compress.c3
-rw-r--r--mysys/my_create.c8
-rw-r--r--mysys/my_delete.c4
-rw-r--r--mysys/my_error.c5
-rw-r--r--mysys/my_getsystime.c40
-rw-r--r--mysys/my_handler.c90
-rw-r--r--mysys/my_init.c47
-rw-r--r--mysys/my_open.c74
-rw-r--r--mysys/my_pread.c6
-rw-r--r--mysys/my_realloc.c11
-rw-r--r--mysys/my_rename.c17
-rw-r--r--mysys/my_symlink.c2
-rw-r--r--mysys/my_sync.c80
-rw-r--r--mysys/safemalloc.c23
21 files changed, 431 insertions, 208 deletions
diff --git a/mysys/array.c b/mysys/array.c
index 8a539f18a20..f11a327232c 100644
--- a/mysys/array.c
+++ b/mysys/array.c
@@ -63,7 +63,8 @@ my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size,
array->size_of_element=element_size;
if ((array->buffer= init_buffer))
DBUG_RETURN(FALSE);
- if (!(array->buffer=(uchar*) my_malloc_ci(element_size*init_alloc,MYF(MY_WME))))
+ if (!(array->buffer=(uchar*) my_malloc_ci(element_size*init_alloc,
+ MYF(MY_WME))))
{
array->max_element=0;
DBUG_RETURN(TRUE);
@@ -179,7 +180,7 @@ uchar *pop_dynamic(DYNAMIC_ARRAY *array)
}
/*
- Replace elemnent in array with given element and index
+ Replace element in array with given element and index
SYNOPSIS
set_dynamic()
@@ -200,42 +201,69 @@ my_bool set_dynamic(DYNAMIC_ARRAY *array, uchar* element, uint idx)
{
if (idx >= array->elements)
{
- if (idx >= array->max_element)
- {
- uint size;
- char *new_ptr;
- size=(idx+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= (char *) 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=(char*) my_realloc(array->buffer,size*
- array->size_of_element,
- MYF(MY_WME | MY_ALLOW_ZERO_PTR))))
- return TRUE;
- array->buffer= (uchar*) new_ptr;
- array->max_element=size;
- }
+ 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);
+ (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);
+ (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
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index 58650733490..0f49dd22bb9 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -1701,6 +1701,7 @@ int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
my_bool append_cache;
my_off_t pos_in_file;
DBUG_ENTER("my_b_flush_io_cache");
+ DBUG_PRINT("enter", ("cache: 0x%lx", (long) info));
if (!(append_cache = (info->type == SEQ_READ_APPEND)))
need_append_buffer_lock=0;
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index c81da9a469a..bb9a06747b9 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -105,6 +105,7 @@
#include <keycache.h>
#include "my_static.h"
#include <m_string.h>
+#include <my_bit.h>
#include <errno.h>
#include <stdarg.h>
@@ -1262,12 +1263,12 @@ static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block)
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));
- KEYCACHE_DBUG_ASSERT(keycache->blocks_available >= 0);
#endif
}
@@ -2360,9 +2361,9 @@ restart:
(block->hash_link->diskpos == filepos)));
*page_st=page_status;
KEYCACHE_DBUG_PRINT("find_key_block",
- ("fd: %d pos: %lu block->status: %u page_status: %u",
+ ("fd: %d pos: %lu block->status: %u page_status: %d",
file, (ulong) filepos, block->status,
- (uint) page_status));
+ page_status));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache2",
@@ -2513,10 +2514,10 @@ static void read_block(KEY_CACHE *keycache,
*/
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)))
+ 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;
@@ -2534,12 +2535,12 @@ uchar *key_cache_read(KEY_CACHE *keycache,
uint status;
int page_st;
- /*
+ /*
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
@@ -2976,9 +2977,10 @@ int key_cache_write(KEY_CACHE *keycache,
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));
+ ("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)
{
@@ -3184,7 +3186,6 @@ int key_cache_write(KEY_CACHE *keycache,
a flush.
*/
block->status&= ~BLOCK_FOR_UPDATE;
-
set_if_smaller(block->offset, offset);
set_if_bigger(block->length, read_length+offset);
diff --git a/mysys/mf_tempfile.c b/mysys/mf_tempfile.c
index 9460f27b104..40016210de4 100644
--- a/mysys/mf_tempfile.c
+++ b/mysys/mf_tempfile.c
@@ -136,6 +136,7 @@ File create_temp_file(char *to, const char *dir, const char *prefix,
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;
}
diff --git a/mysys/my_atomic.c b/mysys/my_atomic.c
index 6a30267eb80..aa04d55f624 100644
--- a/mysys/my_atomic.c
+++ b/mysys/my_atomic.c
@@ -17,11 +17,10 @@
#include <my_pthread.h>
#ifndef HAVE_INLINE
-/*
- the following will cause all inline functions to be instantiated
-*/
+/* the following will cause all inline functions to be instantiated */
#define HAVE_INLINE
-#define static extern
+#undef STATIC_INLINE
+#define STATIC_INLINE extern
#endif
#include <my_atomic.h>
@@ -35,7 +34,7 @@
*/
int my_atomic_initialize()
{
- DBUG_ASSERT(sizeof(intptr) == sizeof(void *));
+ 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;
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
index 5a9b1187c83..2881eb1ebd2 100644
--- a/mysys/my_bit.c
+++ b/mysys/my_bit.c
@@ -13,23 +13,18 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Some useful bit functions */
+#include <my_global.h>
-#include "mysys_priv.h"
-
-/*
- Find smallest X in 2^X >= value
- This can be used to divide a number with value by doing a shift instead
-*/
+#ifndef HAVE_INLINE
+/* the following will cause all inline functions to be instantiated */
+#define HAVE_INLINE
+#undef STATIC_INLINE
+#define STATIC_INLINE extern
+#endif
-uint my_bit_log2(ulong value)
-{
- uint bit;
- for (bit=0 ; value > 1 ; value>>=1, bit++) ;
- return bit;
-}
+#include <my_bit.h>
-static char nbits[256] = {
+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,
@@ -48,60 +43,29 @@ static char nbits[256] = {
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
};
-uint my_count_bits(ulonglong v)
-{
-#if SIZEOF_LONG_LONG > 4
- /* The following code is a bit faster on 16 bit machines than if we would
- only shift v */
- ulong v2=(ulong) (v >> 32);
- return (uint) (uchar) (nbits[(uchar) v] +
- nbits[(uchar) (v >> 8)] +
- nbits[(uchar) (v >> 16)] +
- nbits[(uchar) (v >> 24)] +
- nbits[(uchar) (v2)] +
- nbits[(uchar) (v2 >> 8)] +
- nbits[(uchar) (v2 >> 16)] +
- nbits[(uchar) (v2 >> 24)]);
-#else
- return (uint) (uchar) (nbits[(uchar) v] +
- nbits[(uchar) (v >> 8)] +
- nbits[(uchar) (v >> 16)] +
- nbits[(uchar) (v >> 24)]);
-#endif
-}
-
-uint my_count_bits_ushort(ushort v)
-{
- return nbits[v];
-}
-
-
/*
- Next highest power of two
-
- SYNOPSIS
- my_round_up_to_next_power()
- v Value to check
-
- RETURN
- Next or equal power of 2
- Note: 0 will return 0
-
- NOTES
- Algorithm by Sean Anderson, according to:
- http://graphics.stanford.edu/~seander/bithacks.html
- (Orignal code public domain)
-
- Comments shows how this works with 01100000000000000000000000001011
+ 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
+};
-uint32 my_round_up_to_next_power(uint32 v)
-{
- v--; /* 01100000000000000000000000001010 */
- v|= v >> 1; /* 01110000000000000000000000001111 */
- v|= v >> 2; /* 01111100000000000000000000001111 */
- v|= v >> 4; /* 01111111110000000000000000001111 */
- v|= v >> 8; /* 01111111111111111100000000001111 */
- v|= v >> 16; /* 01111111111111111111111111111111 */
- return v+1; /* 10000000000000000000000000000000 */
-}
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index 10eff40b9ed..e127b2584ae 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -38,6 +38,7 @@
#include "mysys_priv.h"
#include <my_bitmap.h>
#include <m_string.h>
+#include <my_bit.h>
void create_last_word_mask(MY_BITMAP *map)
{
diff --git a/mysys/my_compress.c b/mysys/my_compress.c
index bc9f8317487..0d076e77c35 100644
--- a/mysys/my_compress.c
+++ b/mysys/my_compress.c
@@ -181,7 +181,8 @@ int packfrm(uchar *data, size_t 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_PRINT("info", ("org_len: %lu comp_len: %lu", (ulong) org_len,
+ (ulong) comp_len));
DBUG_DUMP("compressed", data, org_len);
error= 2;
diff --git a/mysys/my_create.c b/mysys/my_create.c
index 55878318ead..7c97ef0201a 100644
--- a/mysys/my_create.c
+++ b/mysys/my_create.c
@@ -17,6 +17,7 @@
#include <my_dir.h>
#include "mysys_err.h"
#include <errno.h>
+#include <my_sys.h>
#if defined(__WIN__)
#include <share.h>
#endif
@@ -52,6 +53,13 @@ File my_create(const char *FileName, int CreateFlags, int access_flags,
fd = open(FileName, access_flags);
#endif
+ if ((MyFlags & MY_SYNC_DIR) && (fd >=0) &&
+ my_sync_dir_by_file(FileName, MyFlags))
+ {
+ my_close(fd, MyFlags);
+ fd= -1;
+ }
+
DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_CREATE,
EE_CANTCREATEFILE, MyFlags));
} /* my_create */
diff --git a/mysys/my_delete.c b/mysys/my_delete.c
index bac3e2513e1..6487ab4d6b8 100644
--- a/mysys/my_delete.c
+++ b/mysys/my_delete.c
@@ -15,6 +15,7 @@
#include "mysys_priv.h"
#include "mysys_err.h"
+#include <my_sys.h>
int my_delete(const char *name, myf MyFlags)
{
@@ -29,6 +30,9 @@ int my_delete(const char *name, myf MyFlags)
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 */
diff --git a/mysys/my_error.c b/mysys/my_error.c
index e8fd8b938ee..75701536dd3 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -84,11 +84,6 @@ int my_error(int nr, myf MyFlags, ...)
if (nr <= meh_p->meh_last)
break;
-#ifdef SHARED_LIBRARY
- if ((meh_p == &my_errmsgs_globerrs) && ! globerrs[0])
- init_glob_errs();
-#endif
-
/* get the error message string. Default, if NULL or empty string (""). */
if (! (format= (meh_p && (nr >= meh_p->meh_first)) ?
meh_p->meh_errmsgs[nr - meh_p->meh_first] : NULL) || ! *format)
diff --git a/mysys/my_getsystime.c b/mysys/my_getsystime.c
index 43bb6c08af9..759e0d302a7 100644
--- a/mysys/my_getsystime.c
+++ b/mysys/my_getsystime.c
@@ -35,9 +35,9 @@ ulonglong my_getsystime()
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 ((t_cnt.QuadPart / query_performance_frequency * 10000000) +
+ (t_cnt.QuadPart % query_performance_frequency * 10000000 /
+ query_performance_frequency) + query_performance_offset);
}
return 0;
#elif defined(__NETWARE__)
@@ -108,7 +108,9 @@ ulonglong my_micro_time()
if (query_performance_frequency)
{
QueryPerformanceCounter((LARGE_INTEGER*) &newtime);
- newtime/= (query_performance_frequency * 1000000);
+ return ((newtime / query_performance_frequency * 10000000) +
+ (newtime % query_performance_frequency * 10000000 /
+ query_performance_frequency));
}
else
newtime= (GetTickCount() * 1000); /* GetTickCount only returns milliseconds */
@@ -117,7 +119,9 @@ ulonglong my_micro_time()
return gethrtime()/1000;
#else
struct timeval t;
- /* The following loop is here because gettimeofday may fail on some systems */
+ /*
+ 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;
@@ -131,18 +135,18 @@ ulonglong my_micro_time()
SYNOPSIS
my_micro_time_and_time()
- time_arg Will be set to seconds since epoch (00:00:00 UTC, January 1,
- 1970)
+ 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)
+ 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()
+ 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
@@ -160,13 +164,13 @@ ulonglong my_micro_time_and_time(time_t *time_arg)
newtime/= (query_performance_frequency * 1000000);
}
else
- newtime= (GetTickCount() * 1000); /* GetTickCount only returns milliseconds */
+ newtime= (GetTickCount() * 1000); /* GetTickCount only returns millisec. */
(void) time(time_arg);
return newtime;
#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
+ 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;
@@ -184,7 +188,9 @@ ulonglong my_micro_time_and_time(time_t *time_arg)
return cur_gethrtime/1000;
#else
struct timeval t;
- /* The following loop is here because gettimeofday may fail on some systems */
+ /*
+ The following loop is here because gettimeofday may fail on some systems
+ */
while (gettimeofday(&t, NULL) != 0)
{}
*time_arg= t.tv_sec;
@@ -203,8 +209,8 @@ ulonglong my_micro_time_and_time(time_t *time_arg)
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.
+ if my_micro_time() uses a function that can safely be converted to the
+ current time.
RETURN
current time
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 1c3bb20426e..bf75d992f9d 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -16,9 +16,12 @@
MA 02111-1307, USA */
#include <my_global.h>
-#include "my_handler.h"
+#include <m_ctype.h>
+#include <my_base.h>
+#include <my_handler.h>
+#include <my_sys.h>
-int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
+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)
{
@@ -174,7 +177,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
next_key_length=key_length-b_length-pack_length;
if (piks &&
- (flag=mi_compare_text(keyseg->charset,a,a_length,b,b_length,
+ (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))))
@@ -187,7 +190,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
{
uint length=(uint) (end-a), a_length=length, b_length=length;
if (piks &&
- (flag= mi_compare_text(keyseg->charset, a, a_length, b, b_length,
+ (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))))
@@ -235,7 +238,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
next_key_length=key_length-b_length-pack_length;
if (piks &&
- (flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
+ (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 |
@@ -482,12 +485,15 @@ end:
DESCRIPTION
Find the first NULL value in index-suffix values tuple.
- TODO Consider optimizing this fuction or its use so we don't search for
- NULL values in completely NOT NULL index suffixes.
+
+ 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.
+ 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)
@@ -557,3 +563,69 @@ HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
}
return keyseg;
}
+
+
+/*
+ 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",
+ "Undefined handler error 122",
+ "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",
+ "Unknown handler error"
+};
+
+
+/*
+ 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.
+*/
+
+
+void my_handler_error_register(void)
+{
+ my_error_register(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/mysys/my_init.c b/mysys/my_init.c
index 6d1b9ec04be..eaa8e36e39c 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -43,6 +43,7 @@ static void netware_init();
my_bool my_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)
{
@@ -76,6 +77,7 @@ my_bool my_init(void)
mysys_usage_id++;
my_umask= 0660; /* Default umask for new files */
my_umask_dir= 0700; /* Default umask for new directories */
+ init_glob_errs();
#if defined(THREAD) && defined(SAFE_MUTEX)
safe_mutex_global_init(); /* Must be called early */
#endif
@@ -343,6 +345,30 @@ static void my_win_init(void)
_tzset();
+ /* The following is used by time functions */
+#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10)
+#define MS 10000000
+ {
+ 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);
+ }
+ }
+
/* apre la chiave HKEY_LOCAL_MACHINES\software\MySQL */
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,(LPCTSTR)targetKey,0,
KEY_READ,&hSoftMysql) != ERROR_SUCCESS)
@@ -380,27 +406,6 @@ static void my_win_init(void)
/* chiude la chiave */
RegCloseKey(hSoftMysql) ;
- /* The following is used by time functions */
-#define OFFSET_TO_EPOC ((__int64) 134774 * 24 * 60 * 60 * 1000 * 1000 * 10)
-#define MS 10000000
- {
- FILETIME ft;
- LARGE_INTEGER li, t_cnt;
- DBUG_ASSERT(sizeof(LARGE_INTEGER) == sizeof(query_performance_frequency));
- if (QueryPerformanceFrequency((LARGE_INTEGER *)&query_performance_frequency))
- 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);
- }
- }
DBUG_VOID_RETURN ;
}
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 938dbc5dde2..fe7f65c450b 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -71,6 +71,7 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
#else
fd = open((char *) FileName, Flags);
#endif
+
DBUG_RETURN(my_register_filename(fd, FileName, FILE_BY_OPEN,
EE_FILENOTFOUND, MyFlags));
} /* my_open */
@@ -124,61 +125,66 @@ int my_close(File fd, myf MyFlags)
SYNOPSIS
my_register_filename()
- fd
- FileName
- type_file_type
+ 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 >= 0)
{
if ((uint) fd >= my_file_limit)
{
#if defined(THREAD) && !defined(HAVE_PREAD)
- (void) my_close(fd,MyFlags);
- my_errno=EMFILE;
- if (MyFlags & (MY_FFNF | MY_FAE | MY_WME))
- my_error(EE_OUT_OF_FILERESOURCES, MYF(ME_BELL+ME_WAITTANG),
- FileName, my_errno);
- return(-1);
-#endif
+ my_errno= EMFILE;
+#else
thread_safe_increment(my_file_opened,&THR_LOCK_open);
- return(fd); /* safeguard */
+ DBUG_RETURN(fd); /* safeguard */
+#endif
}
- pthread_mutex_lock(&THR_LOCK_open);
- if ((my_file_info[fd].name = (char*) my_strdup(FileName,MyFlags)))
+ else
{
- my_file_opened++;
- my_file_total_opened++;
- my_file_info[fd].type = type_of_file;
+ pthread_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(THREAD) && !defined(HAVE_PREAD)
- pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&my_file_info[fd].mutex,MY_MUTEX_INIT_FAST);
#endif
+ pthread_mutex_unlock(&THR_LOCK_open);
+ DBUG_PRINT("exit",("fd: %d",fd));
+ DBUG_RETURN(fd);
+ }
pthread_mutex_unlock(&THR_LOCK_open);
- DBUG_PRINT("exit",("fd: %d",fd));
- return(fd);
+ my_errno= ENOMEM;
}
- pthread_mutex_unlock(&THR_LOCK_open);
(void) my_close(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)) {
- if (my_errno == EMFILE) {
- DBUG_PRINT("error",("print err: %d",EE_OUT_OF_FILERESOURCES));
- my_error(EE_OUT_OF_FILERESOURCES, MYF(ME_BELL+ME_WAITTANG),
- FileName, my_errno);
- } else {
- DBUG_PRINT("error",("print err: %d",error_message_number));
- my_error(error_message_number, MYF(ME_BELL+ME_WAITTANG),
- FileName, my_errno);
- }
+ 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);
}
- return(fd);
+ DBUG_RETURN(-1);
}
#ifdef __WIN__
diff --git a/mysys/my_pread.c b/mysys/my_pread.c
index 6e98132db73..de7a2b611ed 100644
--- a/mysys/my_pread.c
+++ b/mysys/my_pread.c
@@ -63,12 +63,12 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
pthread_mutex_unlock(&my_file_info[Filedes].mutex);
#else
if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count)))
- my_errno= errno;
+ my_errno= errno ? errno : -1;
#endif
if (error || readbytes != Count)
{
DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
- (int) readbytes, (uint) Count,Filedes,my_errno));
+ (int) readbytes, (uint) Count,Filedes,my_errno));
#ifdef THREAD
if ((readbytes == 0 || readbytes == (size_t) -1) && errno == EINTR)
{
@@ -115,7 +115,7 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
RETURN
(size_t) -1 Error
# Number of bytes read
- */
+*/
size_t my_pwrite(int Filedes, const uchar *Buffer, size_t Count,
my_off_t offset, myf MyFlags)
diff --git a/mysys/my_realloc.c b/mysys/my_realloc.c
index c7cf1323cd4..a55282e03a0 100644
--- a/mysys/my_realloc.c
+++ b/mysys/my_realloc.c
@@ -22,6 +22,16 @@
/* My memory re allocator */
+/**
+ @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;
@@ -29,6 +39,7 @@ void* my_realloc(void* oldpoint, size_t size, myf my_flags)
DBUG_PRINT("my",("ptr: 0x%lx size: %lu my_flags: %d", (long) 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
diff --git a/mysys/my_rename.c b/mysys/my_rename.c
index 6a6aa6a5796..39e6056a9e4 100644
--- a/mysys/my_rename.c
+++ b/mysys/my_rename.c
@@ -16,8 +16,9 @@
#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)
@@ -60,5 +61,19 @@ int my_rename(const char *from, const char *to, myf MyFlags)
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/mysys/my_symlink.c b/mysys/my_symlink.c
index 810c0c72632..98059ccd508 100644
--- a/mysys/my_symlink.c
+++ b/mysys/my_symlink.c
@@ -84,6 +84,8 @@ int my_symlink(const char *content, const char *linkname, myf MyFlags)
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 */
}
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index 64fce3aac21..ba6964b00d6 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -48,6 +48,16 @@ int my_sync(File fd, myf 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)
res= fdatasync(fd);
#elif defined(HAVE_FSYNC)
@@ -55,6 +65,7 @@ int my_sync(File fd, myf my_flags)
#elif defined(__WIN__)
res= _commit(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);
@@ -66,10 +77,79 @@ int my_sync(File fd, myf my_flags)
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
+*/
+int my_sync_dir(const char *dir_name, myf my_flags)
+{
+#ifdef NEED_EXPLICIT_SYNC_DIR
+ DBUG_ENTER("my_sync_dir");
+ DBUG_PRINT("my",("Dir: '%s' my_flags: %d", dir_name, my_flags));
+ File dir_fd;
+ int res= 0;
+ const char *correct_dir_name;
+ /* 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
+ return 0;
+#endif
+}
+
+
+/*
+ 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
+*/
+int my_sync_dir_by_file(const char *file_name, myf my_flags)
+{
+#ifdef NEED_EXPLICIT_SYNC_DIR
+ 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
+ return 0;
+#endif
+}
+
diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c
index 7a2f448b2dc..a7a7bcc9c53 100644
--- a/mysys/safemalloc.c
+++ b/mysys/safemalloc.c
@@ -430,6 +430,29 @@ void TERMINATE(FILE *file, uint flag)
}
+/*
+ Report where a piece of memory was allocated
+
+ This is usefull to call from withing a debugger
+*/
+
+
+void sf_malloc_report_allocated(void *memory)
+{
+ struct st_irem *irem;
+ for (irem= sf_malloc_root ; irem ; irem=irem->next)
+ {
+ char *data= (((char*) irem) + ALIGN_SIZE(sizeof(struct st_irem)) +
+ sf_malloc_prehunc);
+ if (data <= (char*) memory && (char*) memory <= data + irem->datasize)
+ {
+ printf("%u bytes at 0x%lx, allocated at line %u in '%s'\n",
+ irem->datasize, (long) data, irem->linenum, irem->filename);
+ break;
+ }
+ }
+}
+
/* Returns 0 if chunk is ok */
static int _checkchunk(register struct st_irem *irem, const char *filename,