summaryrefslogtreecommitdiff
path: root/mysys
diff options
context:
space:
mode:
Diffstat (limited to 'mysys')
-rw-r--r--mysys/Makefile.am16
-rw-r--r--mysys/charset-def.c5
-rw-r--r--mysys/charset.c83
-rw-r--r--mysys/charset2html.c177
-rw-r--r--mysys/default.c441
-rw-r--r--mysys/default_modify.c164
-rw-r--r--mysys/errors.c10
-rw-r--r--mysys/hash.c2
-rw-r--r--mysys/list.c2
-rw-r--r--mysys/mf_getdate.c42
-rw-r--r--mysys/mf_iocache.c19
-rw-r--r--mysys/mf_iocache2.c7
-rw-r--r--mysys/mf_keycache.c10
-rw-r--r--mysys/my_alloc.c19
-rw-r--r--mysys/my_bit.c5
-rw-r--r--mysys/my_bitmap.c70
-rw-r--r--mysys/my_chsize.c14
-rw-r--r--mysys/my_error.c266
-rw-r--r--mysys/my_getopt.c3
-rw-r--r--mysys/my_handler.c25
-rw-r--r--mysys/my_largepage.c167
-rw-r--r--mysys/my_mmap.c91
-rw-r--r--mysys/my_new.cc9
-rw-r--r--mysys/my_open.c9
-rw-r--r--mysys/my_static.c8
-rw-r--r--mysys/my_sync.c32
-rw-r--r--mysys/my_thr_init.c11
-rw-r--r--mysys/ptr_cmp.c39
-rw-r--r--mysys/raid.cc14
-rw-r--r--mysys/thr_alarm.c1
-rw-r--r--mysys/thr_lock.c34
31 files changed, 1234 insertions, 561 deletions
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index ab35ccb21ba..03ee692645f 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -17,8 +17,7 @@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir= $(prefix)
-INCLUDES = @MT_INCLUDES@ \
- @ZLIB_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir)
+INCLUDES = @ZLIB_INCLUDES@ -I$(top_srcdir)/include -I$(srcdir)
pkglib_LIBRARIES = libmysys.a
LDADD = libmysys.a ../dbug/libdbug.a \
../strings/libmystrings.a
@@ -26,7 +25,7 @@ noinst_HEADERS = mysys_priv.h my_static.h \
my_os2cond.c my_os2dirsrch.c my_os2dirsrch.h \
my_os2dlfcn.c my_os2file64.c my_os2mutex.c \
my_os2thread.c my_os2tls.c
-libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
+libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
mf_path.c mf_loadpath.c my_file.c \
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c \
@@ -49,15 +48,16 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
my_chsize.c my_lread.c my_lwrite.c my_clock.c \
my_quick.c my_lockmem.c my_static.c \
my_sync.c my_getopt.c my_mkdir.c \
- default.c my_compress.c checksum.c raid.cc \
+ default_modify.c default.c \
+ my_compress.c checksum.c raid.cc \
my_net.c my_semaphore.c my_port.c my_sleep.c \
charset.c charset-def.c my_bitmap.c my_bit.c md5.c \
my_gethostbyname.c rijndael.c my_aes.c sha1.c \
- my_handler.c my_netware.c my_windac.c my_access.c
+ my_handler.c my_netware.c my_largepage.c \
+ my_windac.c my_access.c
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
-noinst_PROGRAMS = charset2html @THREAD_LPROGRAMS@
# test_dir_DEPENDENCIES= $(LIBRARIES)
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
@@ -67,6 +67,7 @@ DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
+ -DDEFAULT_HOME_ENV=MYSQL_HOME \
@DEFS@
libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@
@@ -105,9 +106,6 @@ test_dir$(EXEEXT): test_dir.c $(LIBRARIES)
test_charset$(EXEEXT): test_charset.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS)
-charset2html$(EXEEXT): charset2html.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $(srcdir)/charset2html.c $(LDADD) $(LIBS)
-
testhash$(EXEEXT): testhash.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS)
diff --git a/mysys/charset-def.c b/mysys/charset-def.c
index 1fa87b715a8..0464ba893fb 100644
--- a/mysys/charset-def.c
+++ b/mysys/charset-def.c
@@ -97,6 +97,11 @@ my_bool init_compiled_charsets(myf flags __attribute__((unused)))
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);
diff --git a/mysys/charset.c b/mysys/charset.c
index 4b7ad3e59f4..534a6aa998e 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -547,10 +547,10 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_PRINT("enter",("name: '%s'", cs_name));
(void) init_available_charsets(MYF(0)); /* If it isn't initialized */
-
+
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];
@@ -561,22 +561,35 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
DBUG_RETURN(cs);
}
-
-ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
+/*
+ NOTE
+ to keep old C API, to_length may be 0 to mean "big enough"
+ RETURN
+ the length of the escaped string or ~0 if it did not fit.
+*/
+ulong escape_string_for_mysql(CHARSET_INFO *charset_info,
+ char *to, ulong to_length,
const char *from, ulong length)
{
const char *to_start= to;
- const char *end;
+ const char *end, *to_end=to_start + (to_length ? to_length-1 : 2*length);
+ my_bool overflow=0;
#ifdef USE_MB
my_bool use_mb_flag= use_mb(charset_info);
#endif
- for (end= from + length; from != end; from++)
+ for (end= from + length; from < end; from++)
{
+ char escape=0;
#ifdef USE_MB
- int l;
- if (use_mb_flag && (l= my_ismbchar(charset_info, from, end)))
+ int tmp_length;
+ if (use_mb_flag && (tmp_length= my_ismbchar(charset_info, from, end)))
{
- while (l--)
+ if (to + tmp_length > to_end)
+ {
+ overflow=1;
+ break;
+ }
+ while (tmp_length--)
*to++= *from++;
from--;
continue;
@@ -592,46 +605,54 @@ ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
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 && (l= my_mbcharlen(charset_info, *from)) > 1)
- {
- *to++= '\\';
- *to++= *from;
- continue;
- }
+ 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' */
- *to++= '\\';
- *to++= '0';
+ escape= '0';
break;
case '\n': /* Must be escaped for logs */
- *to++= '\\';
- *to++= 'n';
+ escape= 'n';
break;
case '\r':
- *to++= '\\';
- *to++= 'r';
+ escape= 'r';
break;
case '\\':
- *to++= '\\';
- *to++= '\\';
+ escape= '\\';
break;
case '\'':
- *to++= '\\';
- *to++= '\'';
+ escape= '\'';
break;
case '"': /* Better safe than sorry */
- *to++= '\\';
- *to++= '"';
+ escape= '"';
break;
case '\032': /* This gives problems on Win32 */
- *to++= '\\';
- *to++= 'Z';
+ escape= 'Z';
break;
- default:
+ }
+ if (escape)
+ {
+ if (to + 2 > to_end)
+ {
+ overflow=1;
+ break;
+ }
+ *to++= '\\';
+ *to++= escape;
+ }
+ else
+ {
+ if (to + 1 > to_end)
+ {
+ overflow=1;
+ break;
+ }
*to++= *from;
}
}
*to= 0;
- return (ulong) (to - to_start);
+ return overflow ? (ulong)~0 : (ulong) (to - to_start);
}
+
diff --git a/mysys/charset2html.c b/mysys/charset2html.c
deleted file mode 100644
index 96862ff16a1..00000000000
--- a/mysys/charset2html.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; either version 2 of the License, or
- (at your option) any later version.
-
- 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 Alexander Barkov to check what
- a charset is in your favorite web browser
-*/
-
-#include <my_global.h>
-#include <m_ctype.h>
-#include <my_sys.h>
-#include <mysql_version.h>
-
-#include <stdio.h>
-
-typedef struct char_info_st
-{
- int cod;
- int srt;
- int uni;
- int low;
- int upp;
- int ctp;
-} MY_CH;
-
-static int chcmp(const void *vf, const void *vs)
-{
- const MY_CH *f=vf;
- const MY_CH *s=vs;
-
- return f->srt-s->srt ? f->srt-s->srt : f->uni-s->uni;
-}
-
-static void print_cs(CHARSET_INFO *cs)
-{
- uint i;
- int srt;
- int clr=0;
- MY_CH ch[256];
-
- printf("<HTML>\n");
- printf("<HEAD>\n");
- printf("</HEAD>\n");
- printf("<BODY><PRE>\n");
- printf("Charset %s\n",cs->name);
-
- printf("<TABLE>\n");
- printf("<TR><TH>Code<TH>Uni<TH>Sort<TH>Ctype<TH>Ch<TH>Lo<TH>Up</TR>");
-
- for (i=0; i<256; i++)
- {
- ch[i].cod=i;
- ch[i].srt=cs->sort_order ? cs->sort_order[i] : i;
- ch[i].uni=cs->tab_to_uni[i];
- ch[i].low=cs->tab_to_uni[cs->to_lower[i]];
- ch[i].upp=cs->tab_to_uni[cs->to_upper[i]];
- ch[i].ctp=cs->ctype[i+1];
- }
-
- qsort(ch,256,sizeof(MY_CH),&chcmp);
- srt=ch[0].srt;
-
- for (i=0; i<256; i++)
- {
- clr = (srt!=ch[i].srt) ? !clr : clr;
-
- printf("<TR bgcolor=#%s>",clr ? "DDDDDD" : "EEEE99");
- printf("<TD>%02X",ch[i].cod);
- printf("<TD>%04X",ch[i].uni);
- printf("<TD>%02X",ch[i].srt);
-
- printf("<TD>%s%s%s%s%s%s%s%s",
- ch[i].ctp & _MY_U ? "U" : "",
- ch[i].ctp & _MY_L ? "L" : "",
- ch[i].ctp & _MY_NMR ? "N" : "",
- ch[i].ctp & _MY_SPC ? "S" : "",
- ch[i].ctp & _MY_PNT ? "P" : "",
- ch[i].ctp & _MY_CTR ? "C" : "",
- ch[i].ctp & _MY_B ? "B" : "",
- ch[i].ctp & _MY_X ? "X" : "");
-
- if ((ch[i].uni >= 0x80) && (ch[i].uni <= 0x9F))
- {
- /*
- Control characters 0x0080..0x009F are dysplayed by some
- browers as if they were letters. Don't print them to
- avoid confusion.
- */
- printf("<TD>ctrl<TD>ctrl<TD>ctrl");
- }
- else
- {
- printf("<TD>&#%d;",ch[i].uni);
- printf("<TD>&#%d;",ch[i].low);
- printf("<TD>&#%d;",ch[i].upp);
- }
- printf("</TR>\n");
- srt=ch[i].srt;
- }
- printf("</TABLE>\n");
- printf("</PRE></BODY>\n");
- printf("</HTML>\n");
-}
-
-static void print_index()
-{
- CHARSET_INFO **cs;
- int clr=0;
-
- get_charset_by_name("",MYF(0)); /* To execute init_available_charsets */
-
- printf("All charsets\n");
- printf("<table border=1>\n");
- printf("<tr bgcolor=EEEE99><th>ID<th>Charset<th>Collation<th>Def<th>Bin<th>Com<th>Comment\n");
- for (cs=all_charsets ; cs < all_charsets+256; cs++)
- {
- if (!cs[0])
- continue;
- printf("<tr bgcolor=#%s><td><a href=\"?%s\">%d</a><td>%s<td>%s<td>%s<td>%s<td>%s<td>%s\n",
- (clr= !clr) ? "DDDDDD" : "EEEE99",
- cs[0]->name,cs[0]->number,cs[0]->csname,
- cs[0]->name,
- (cs[0]->state & MY_CS_PRIMARY) ? "def " : "&nbsp;",
- (cs[0]->state & MY_CS_BINSORT) ? "bin " : "&nbsp;",
- (cs[0]->state & MY_CS_COMPILED) ? "com " : "&nbsp;",
- cs[0]->comment);
- }
- printf("</table>\n");
-}
-
-int main(int argc, char **argv) {
- const char *the_set = NULL;
- int argcnt = 1;
- CHARSET_INFO *cs;
-
- if (getenv("SCRIPT_NAME"))
- {
- printf("Content-Type: text/html\r\n\r\n");
- }
- my_init();
-
- if (argc > argcnt && argv[argcnt][0] == '-' && argv[argcnt][1] == '#')
- DBUG_PUSH(argv[argcnt++]+2);
-
- if (argc > argcnt)
- the_set = argv[argcnt++];
-
- if (argc > argcnt)
- charsets_dir = argv[argcnt++];
-
- if (!the_set)
- {
- print_index();
- return 0;
- }
-
- if (!(cs= get_charset_by_name(the_set, MYF(MY_WME))))
- return 1;
-
- print_cs(cs);
-
- return 0;
-}
diff --git a/mysys/default.c b/mysys/default.c
index 9510cfb3464..e28161ba7b0 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -37,48 +37,187 @@
#include "m_string.h"
#include "m_ctype.h"
#include <my_dir.h>
+#ifdef __WIN__
+#include <winbase.h>
+#endif
char *defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
-const char *default_directories[]= {
-#ifdef __WIN__
-"C:/",
-#elif defined(__NETWARE__)
-"sys:/etc/",
-#else
-"/etc/",
-#endif
-#ifdef DATADIR
-DATADIR,
-#endif
-"", /* Place for defaults_extra_dir */
-#if !defined(__WIN__) && !defined(__NETWARE__)
-"~/",
-#endif
-NullS,
-};
+#define MAX_DEFAULT_DIRS 5
+const char *default_directories[MAX_DEFAULT_DIRS + 1];
#ifdef __WIN__
static const char *f_extensions[]= { ".ini", ".cnf", 0 };
+#define NEWLINE "\r\n"
+static char system_dir[FN_REFLEN], shared_system_dir[FN_REFLEN];
#else
static const char *f_extensions[]= { ".cnf", 0 };
+#define NEWLINE "\n"
#endif
-static int search_default_file(DYNAMIC_ARRAY *args,MEM_ROOT *alloc,
- const char *dir, const char *config_file,
- TYPELIB *group);
+/*
+ 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_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
+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,
- TYPELIB *group, int recursion_level);
+ const char *config_file, int recursion_level);
+static void init_default_directories();
static char *remove_end_comment(char *ptr);
/*
+ 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
+
+ This function looks for config files in default directories. Then it
+ travesrses each of the files and calls func to process each option.
+
+ RETURN
+ 0 ok
+ 1 given cinf_file doesn't exist
+*/
+
+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 **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 */
+ get_defaults_files(*argc, *argv,
+ (char **)&forced_default_file,
+ (char **)&forced_extra_defaults);
+ if (forced_default_file)
+ forced_default_file= strchr(forced_default_file,'=')+1;
+ if (forced_extra_defaults)
+ defaults_extra_file= strchr(forced_extra_defaults,'=')+1;
+
+ (*args_used)+= (forced_default_file ? 1 : 0) +
+ (forced_extra_defaults ? 1 : 0);
+
+ if (forced_default_file)
+ {
+ if ((error= search_default_file_with_ext(func, func_ctx, "", "",
+ forced_default_file, 0)) < 0)
+ goto err;
+ if (error > 0)
+ {
+ fprintf(stderr, "Could not open required defaults file: %s\n",
+ forced_default_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 (defaults_extra_file)
+ {
+ if ((error= search_default_file_with_ext(func, func_ctx, "", "",
+ defaults_extra_file, 0)) < 0)
+ goto err; /* Fatal error */
+ if (error > 0)
+ {
+ fprintf(stderr, "Could not open required defaults file: %s\n",
+ defaults_extra_file);
+ goto err;
+ }
+ }
+ }
+ }
+
+ DBUG_RETURN(error);
+
+err:
+ fprintf(stderr,"Fatal error in defaults handling. Program aborted\n");
+ exit(1);
+ return 0; /* Keep compiler happy */
+}
+
+
+/*
+ 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)
+
+ 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 (find_type((char *)group_name, ctx->group, 3))
+ {
+ if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1)))
+ return 1;
+ if (insert_dynamic(ctx->args, (gptr) &tmp))
+ return 1;
+ strmov(tmp, option);
+ }
+
+ return 0;
+}
+
+
+/*
Gets --defaults-file and --defaults-extra-file options from command line.
SYNOPSIS
@@ -136,7 +275,6 @@ void get_defaults_files(int argc, char **argv,
RETURN
0 ok
1 The given conf_file didn't exists
- 2 The given conf_file was not a normal readable file
*/
@@ -144,16 +282,16 @@ int load_defaults(const char *conf_file, const char **groups,
int *argc, char ***argv)
{
DYNAMIC_ARRAY args;
- const char **dirs, *forced_default_file, *forced_extra_defaults;
TYPELIB group;
my_bool found_print_defaults=0;
uint args_used=0;
int error= 0;
MEM_ROOT alloc;
- char *ptr, **res;
-
+ char *ptr,**res;
+ struct handle_option_ctx ctx;
DBUG_ENTER("load_defaults");
+ init_default_directories();
init_alloc_root(&alloc,512,0);
if (*argc >= 2 && !strcmp(argv[0][1],"--no-defaults"))
{
@@ -173,76 +311,22 @@ int load_defaults(const char *conf_file, const char **groups,
DBUG_RETURN(0);
}
- get_defaults_files(*argc, *argv,
- (char **)&forced_default_file,
- (char **)&forced_extra_defaults);
- if (forced_default_file)
- forced_default_file= strchr(forced_default_file,'=')+1;
- if (forced_extra_defaults)
- defaults_extra_file= strchr(forced_extra_defaults,'=')+1;
-
- args_used+= (forced_default_file ? 1 : 0) + (forced_extra_defaults ? 1 : 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;
- if (forced_default_file)
- {
- if ((error= search_default_file_with_ext(&args, &alloc, "", "",
- forced_default_file,
- &group, 0)) < 0)
- goto err;
- if (error > 0)
- {
- fprintf(stderr, "Could not open required defaults file: %s\n",
- forced_default_file);
- goto err;
- }
- }
- else if (dirname_length(conf_file))
- {
- if ((error= search_default_file(&args, &alloc, NullS, conf_file,
- &group)) < 0)
- goto err;
- }
- else
- {
-#ifdef __WIN__
- char system_dir[FN_REFLEN];
- GetWindowsDirectory(system_dir,sizeof(system_dir));
- if ((search_default_file(&args, &alloc, system_dir, conf_file, &group)))
- goto err;
-#endif
-#if defined(__EMX__) || defined(OS2)
- {
- const char *etc;
- if ((etc= getenv("ETC")) &&
- (search_default_file(&args, &alloc, etc, conf_file,
- &group)) < 0)
- goto err;
- }
-#endif
- for (dirs=default_directories ; *dirs; dirs++)
- {
- if (**dirs)
- {
- if (search_default_file(&args, &alloc, *dirs, conf_file,
- &group) < 0)
- goto err;
- }
- else if (defaults_extra_file)
- {
- if (search_default_file(&args, &alloc, NullS, defaults_extra_file,
- &group) < 0)
- goto err; /* Fatal error */
- }
- }
- }
+
+ ctx.alloc= &alloc;
+ ctx.args= &args;
+ ctx.group= &group;
+
+ error= my_search_option_files(conf_file, argc, argv, &args_used,
+ handle_default_option, (void *) &ctx);
/*
Here error contains <> 0 only if we have a fully specified conf_file
or a forced default file
@@ -302,17 +386,22 @@ void free_defaults(char **argv)
}
-static int search_default_file(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
+static int search_default_file(Process_option_func opt_handler,
+ void *handler_ctx,
const char *dir,
- const char *config_file, TYPELIB *group)
+ 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**) f_extensions; *ext; *ext++)
+ for (ext= (char**) exts_to_use; *ext; *ext++)
{
int error;
- if ((error= search_default_file_with_ext(args, alloc, dir, *ext,
- config_file, group, 0)) < 0)
+ if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
+ dir, *ext,
+ config_file, 0)) < 0)
return error;
}
return 0;
@@ -374,8 +463,10 @@ static char *get_argument(const char *keyword, uint kwlen,
SYNOPSIS
search_default_file_with_ext()
- args Store pointer to found options here
- alloc Allocate strings in this object
+ 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
@@ -387,21 +478,23 @@ static char *get_argument(const char *keyword, uint kwlen,
0 Success
-1 Fatal error, abort
1 File not found (Warning)
- 2 File is not a regular file (Warning)
*/
-static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
- const char *dir, const char *ext,
- const char *config_file,
- TYPELIB *group, int recursion_level)
+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], *ptr, *end, *value, *tmp, **tmp_ext;
+ char name[FN_REFLEN + 10], buff[4096], curr_gr[4096], *ptr, *end, **tmp_ext;
+ char *value, option[4096], tmp[FN_REFLEN];
static const char includedir_keyword[]= "includedir";
static const char include_keyword[]= "include";
const int max_recursion_level= 10;
FILE *fp;
- uint line= 0;
- my_bool read_values= 0, found_group= 0;
+ uint line=0;
+ my_bool found_group=0;
uint i;
MY_DIR *search_dir;
FILEINFO *search_file;
@@ -433,14 +526,14 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
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",
+ fprintf(stderr, "Warning: World-writable config file '%s' is ignored\n",
name);
return 0;
}
}
#endif
- if (!(fp= my_fopen(fn_format(name, name, "", "", 4), O_RDONLY, MYF(0))))
- return 0; /* Ignore wrong files */
+ if (!(fp= my_fopen(name, O_RDONLY, MYF(0))))
+ return 1; /* Ignore wrong files */
while (fgets(buff, sizeof(buff) - 1, fp))
{
@@ -499,14 +592,10 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
if (*tmp_ext)
{
- if (!(tmp= alloc_root(alloc, 2 + strlen(search_file->name)
- + strlen(ptr))))
- goto err;
-
fn_format(tmp, search_file->name, ptr, "",
MY_UNPACK_FILENAME | MY_SAFE_PATH);
- search_default_file_with_ext(args, alloc, "", "", tmp, group,
+ search_default_file_with_ext(opt_handler, handler_ctx, "", "", tmp,
recursion_level + 1);
}
}
@@ -521,7 +610,7 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
name, line)))
goto err;
- search_default_file_with_ext(args, alloc, "", "", ptr, group,
+ search_default_file_with_ext(opt_handler, handler_ctx, "", "", ptr,
recursion_level + 1);
}
@@ -540,7 +629,8 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
}
for ( ; my_isspace(&my_charset_latin1,end[-1]) ; end--) ;/* Remove end space */
end[0]=0;
- read_values=find_type(ptr,group,3) > 0;
+
+ strnmov(curr_gr, ptr, min((uint) (end-ptr)+1, 4096));
continue;
}
if (!found_group)
@@ -550,19 +640,17 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
name,line);
goto err;
}
- if (!read_values)
- continue;
+
+
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)
{
- if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3)))
- goto err;
- strmake(strmov(tmp,"--"),ptr,(uint) (end-ptr));
- if (insert_dynamic(args,(gptr) &tmp))
- goto err;
+ strmake(strmov(option,"--"),ptr,(uint) (end-ptr));
+ if (opt_handler(handler_ctx, curr_gr, option))
+ goto err;
}
else
{
@@ -584,12 +672,7 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
value++;
value_end--;
}
- if (!(tmp=alloc_root(alloc,(uint) (end-ptr)+3 +
- (uint) (value_end-value)+1)))
- goto err;
- if (insert_dynamic(args,(gptr) &tmp))
- goto err;
- ptr=strnmov(strmov(tmp,"--"),ptr,(uint) (end-ptr));
+ ptr=strnmov(strmov(option,"--"),ptr,(uint) (end-ptr));
*ptr++= '=';
for ( ; value != value_end; value++)
@@ -631,6 +714,8 @@ static int search_default_file_with_ext(DYNAMIC_ARRAY *args, MEM_ROOT *alloc,
*ptr++= *value;
}
*ptr=0;
+ if (opt_handler(handler_ctx, curr_gr, option))
+ goto err;
}
}
my_fclose(fp,MYF(0));
@@ -669,44 +754,24 @@ static char *remove_end_comment(char *ptr)
#include <help_start.h>
-void print_defaults(const char *conf_file, const char **groups)
+void my_print_default_files(const char *conf_file)
{
-#ifdef __WIN__
+ const char *empty_list[]= { "", 0 };
my_bool have_ext= fn_ext(conf_file)[0] != 0;
-#endif
+ const char **exts_to_use= have_ext ? empty_list : f_extensions;
char name[FN_REFLEN], **ext;
const char **dirs;
+ init_default_directories();
puts("\nDefault options are read from the following files in the given order:");
if (dirname_length(conf_file))
fputs(conf_file,stdout);
else
{
-#ifdef __WIN__
- GetWindowsDirectory(name,sizeof(name));
- if (!have_ext)
- {
- for (ext= (char**) f_extensions; *ext; *ext++)
- printf("%s\\%s%s ", name, conf_file, *ext);
- }
- else
- printf("%s\\%s ", name, conf_file);
-#endif
-#if defined(__EMX__) || defined(OS2)
- {
- const char *etc;
-
- if ((etc= getenv("ETC")))
- {
- for (ext= (char**) f_extensions; *ext; *ext++)
- printf("%s\\%s%s ", etc, conf_file, *ext);
- }
- }
-#endif
for (dirs=default_directories ; *dirs; dirs++)
{
- for (ext= (char**) f_extensions; *ext; *ext++)
+ for (ext= (char**) exts_to_use; *ext; *ext++)
{
const char *pos;
char *end;
@@ -725,6 +790,12 @@ void print_defaults(const char *conf_file, const char **groups)
}
puts("");
}
+}
+
+void print_defaults(const char *conf_file, const char **groups)
+{
+ my_print_default_files(conf_file);
+
fputs("The following groups are read:",stdout);
for ( ; *groups ; groups++)
{
@@ -739,3 +810,69 @@ void print_defaults(const char *conf_file, const char **groups)
}
#include <help_end.h>
+
+
+/*
+ Create the list of default directories.
+
+ On Microsoft Windows, this is:
+ 1. C:/
+ 2. GetWindowsDirectory()
+ 3. GetSystemWindowsDirectory()
+ 4. getenv(DEFAULT_HOME_ENV)
+ 5. ""
+
+ On Novell NetWare, this is:
+ 1. sys:/etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. ""
+
+ On OS/2, this is:
+ 1. getenv(ETC)
+ 2. /etc/
+ 3. getenv(DEFAULT_HOME_ENV)
+ 4. ""
+ 5. "~/"
+
+ Everywhere else, this is:
+ 1. /etc/
+ 2. getenv(DEFAULT_HOME_ENV)
+ 3. ""
+ 4. "~/"
+
+ */
+
+static void init_default_directories()
+{
+ const char *env, **ptr= default_directories;
+
+#ifdef __WIN__
+ *ptr++= "C:/";
+
+ if (GetWindowsDirectory(system_dir,sizeof(system_dir)))
+ *ptr++= &system_dir;
+#if defined(_MSC_VER) && (_MSC_VER >= 1300)
+ /* Only VC7 and up */
+ /* Only add shared system directory if different from default. */
+ if (GetSystemWindowsDirectory(shared_system_dir,sizeof(shared_system_dir)) &&
+ strcmp(system_dir, shared_system_dir))
+ *ptr++= &shared_system_dir;
+#endif
+
+#elif defined(__NETWARE__)
+ *ptr++= "sys:/etc/";
+#else
+#if defined(__EMX__) || defined(OS2)
+ if ((env= getenv("ETC")))
+ *ptr++= env;
+#endif
+ *ptr++= "/etc/";
+#endif
+ if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
+ *ptr++= env;
+ *ptr++= ""; /* Place for defaults_extra_file */
+#if !defined(__WIN__) && !defined(__NETWARE__)
+ *ptr++= "~/";;
+#endif
+ *ptr= 0; /* end marker */
+}
diff --git a/mysys/default_modify.c b/mysys/default_modify.c
new file mode 100644
index 00000000000..add4317bb56
--- /dev/null
+++ b/mysys/default_modify.c
@@ -0,0 +1,164 @@
+/*
+ Add/remove option to the option file section.
+
+ SYNOPSYS
+ modify_defaults_file()
+ file_location The location of configuration file to edit
+ option option to look for
+ option value The value of the option we would like to set
+ section_name the name of the section
+ remove_option This is true if we want to remove the option.
+ False otherwise.
+ IMPLEMENTATION
+ We open the option file first, then read the file line-by-line,
+ looking for the section we need. At the same time we put these lines
+ into a buffer. Then we look for the option within this section and
+ change/remove it. In the end we get a buffer with modified version of the
+ file. Then we write it to the file, truncate it if needed and close it.
+
+ RETURN
+ 0 - ok
+ 1 - some error has occured. Probably due to the lack of resourses
+ 2 - cannot open the file
+*/
+
+#include "my_global.h"
+#include "mysys_priv.h"
+#include "m_string.h"
+#include <my_dir.h>
+
+#define BUFF_SIZE 1024
+
+#ifdef __WIN__
+#define NEWLINE "\r\n"
+#define NEWLINE_LEN 2
+#else
+#define NEWLINE "\n"
+#define NEWLINE_LEN 1
+#endif
+
+int modify_defaults_file(const char *file_location, const char *option,
+ const char *option_value,
+ const char *section_name, int remove_option)
+{
+ FILE *cnf_file;
+ MY_STAT file_stat;
+ char linebuff[BUFF_SIZE], tmp[BUFF_SIZE], *tmp_ptr, *src_ptr, *dst_ptr,
+ *file_buffer;
+ uint optlen, optval_len, sect_len;
+ my_bool in_section= FALSE;
+ DBUG_ENTER("modify_defaults_file");
+
+ optlen= strlen(option);
+ optval_len= strlen(option_value);
+ sect_len= strlen(section_name);
+
+ if (!(cnf_file= my_fopen(file_location, O_RDWR | O_BINARY, MYF(0))))
+ DBUG_RETURN(2);
+
+ /* my_fstat doesn't use the flag parameter */
+ if (my_fstat(fileno(cnf_file), &file_stat, MYF(0)))
+ goto err;
+
+ /*
+ Reserve space to read the contents of the file and some more
+ for the option we want to add.
+ */
+ if (!(file_buffer= (char*) my_malloc(sizeof(char)*
+ (file_stat.st_size +
+ /* option name len */
+ optlen +
+ /* reserve space for newline */
+ NEWLINE_LEN +
+ /* reserve for '=' char */
+ 1 +
+ /* option value len */
+ optval_len), MYF(MY_WME))))
+ goto malloc_err;
+
+ for (dst_ptr= file_buffer, tmp_ptr= 0;
+ fgets(linebuff, BUFF_SIZE, cnf_file); )
+ {
+ /* Skip over whitespaces */
+ for (src_ptr= linebuff; my_isspace(&my_charset_latin1, *src_ptr);
+ src_ptr++)
+ {}
+
+ if (in_section && !strncmp(src_ptr, option, optlen) &&
+ (*(src_ptr + optlen) == '=' ||
+ my_isspace(&my_charset_latin1, *(src_ptr + optlen)) ||
+ *(src_ptr + optlen) == '\0'))
+ {
+ /* The option under modifying was found in this section. Apply new. */
+ if (!remove_option)
+ dst_ptr= strmov(dst_ptr, tmp);
+ tmp_ptr= 0; /* To mark that we have already applied this */
+ }
+ else
+ {
+ /* If going to new group and we have option to apply, do it now */
+ if (tmp_ptr && *src_ptr == '[')
+ {
+ dst_ptr= strmov(dst_ptr, tmp);
+ tmp_ptr= 0;
+ }
+ dst_ptr= strmov(dst_ptr, linebuff);
+ }
+ /* Look for a section */
+ if (*src_ptr == '[')
+ {
+ /* Copy the line to the buffer */
+ if (!strncmp(++src_ptr, section_name, sect_len))
+ {
+ src_ptr+= sect_len;
+ /* Skip over whitespaces. They are allowed after section name */
+ for (; my_isspace(&my_charset_latin1, *src_ptr); src_ptr++)
+ {}
+
+ if (*src_ptr != ']')
+ continue; /* Missing closing parenthesis. Assume this was no group */
+
+ in_section= TRUE;
+ /* add option */
+ if (!remove_option)
+ {
+ tmp_ptr= strmov(tmp, option);
+ if (*option_value)
+ {
+ *tmp_ptr++= '=';
+ tmp_ptr= strmov(tmp_ptr, option_value);
+ }
+ /* add a newline */
+ strmov(tmp_ptr, NEWLINE);
+ }
+ }
+ else
+ in_section= FALSE; /* mark that this section is of no interest to us */
+ }
+ }
+ /* File ended. New option still remains to apply at the end */
+ if (tmp_ptr)
+ {
+ if (*(dst_ptr - 1) != '\n')
+ *dst_ptr++= '\n';
+ dst_ptr= strmov(dst_ptr, tmp);
+ }
+
+ if (my_chsize(fileno(cnf_file), (my_off_t) (dst_ptr - file_buffer), 0,
+ MYF(MY_WME)) ||
+ my_fseek(cnf_file, 0, MY_SEEK_SET, MYF(0)) ||
+ my_fwrite(cnf_file, file_buffer, (uint) (dst_ptr - file_buffer),
+ MYF(MY_NABP)) ||
+ my_fclose(cnf_file, MYF(MY_WME)))
+ goto err;
+
+ my_free(file_buffer, MYF(0));
+
+ DBUG_RETURN(0);
+
+err:
+ my_free(file_buffer, MYF(0));
+malloc_err:
+ my_fclose(cnf_file, MYF(0));
+ DBUG_RETURN(1); /* out of resources */
+}
diff --git a/mysys/errors.c b/mysys/errors.c
index 05436c9a212..4472b7173fa 100644
--- a/mysys/errors.c
+++ b/mysys/errors.c
@@ -21,7 +21,6 @@
const char * NEAR globerrs[GLOBERRS]=
{
- "File '%s' not found (Errcode: %d)",
"Can't create/write to file '%s' (Errcode: %d)",
"Error reading file '%s' (Errcode: %d)",
"Error writing file '%s' (Errcode: %d)",
@@ -50,20 +49,18 @@ const char * NEAR globerrs[GLOBERRS]=
"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)",
};
void init_glob_errs(void)
{
- my_errmsg[GLOB] = & globerrs[0];
-} /* init_glob_errs */
+ /* This is now done statically. */
+}
#else
void init_glob_errs()
{
- my_errmsg[GLOB] = & globerrs[0];
-
- EE(EE_FILENOTFOUND) = "File '%s' not found (Errcode: %d)";
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)";
@@ -91,5 +88,6 @@ void init_glob_errs()
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)";
}
#endif
diff --git a/mysys/hash.c b/mysys/hash.c
index b829f19dfc8..fe27b5fcb6d 100644
--- a/mysys/hash.c
+++ b/mysys/hash.c
@@ -103,7 +103,7 @@ static inline void hash_free_elements(HASH *hash)
hash_free()
hash the hash to delete elements of
- NOTES: Hash can't be reused wuthing calling hash_init again.
+ NOTES: Hash can't be reused without calling hash_init again.
*/
void hash_free(HASH *hash)
diff --git a/mysys/list.c b/mysys/list.c
index 64fca10dc0b..c3cd6c94b9f 100644
--- a/mysys/list.c
+++ b/mysys/list.c
@@ -28,7 +28,7 @@
LIST *list_add(LIST *root, LIST *element)
{
DBUG_ENTER("list_add");
- DBUG_PRINT("enter",("root: 0x%lx element: %lx", root, element));
+ DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", root, element));
if (root)
{
if (root->prev) /* If add in mid of list */
diff --git a/mysys/mf_getdate.c b/mysys/mf_getdate.c
index 189d43e782a..b12e68cc1f9 100644
--- a/mysys/mf_getdate.c
+++ b/mysys/mf_getdate.c
@@ -19,11 +19,20 @@
#include "mysys_priv.h"
#include <m_string.h>
- /*
- If flag & 1 Return date and time
- If flag & 2 Return short date format YYMMDD
- if flag & 4 Return time in HHMMDD format.
- */
+/*
+ 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 my_string to, int flag, time_t date)
@@ -36,27 +45,36 @@ void get_date(register my_string to, int flag, time_t date)
skr=date ? (time_t) date : time((time_t*) 0);
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
- localtime_r(&skr,&tm_tmp);
+ if (flag & GETDATE_GMT)
+ localtime_r(&skr,&tm_tmp);
+ else
+ gmtime_r(&skr,&tm_tmp);
start_time= &tm_tmp;
#else
- start_time=localtime(&skr);
+ if (flag & GETDATE_GMT)
+ start_time= localtime(&skr);
+ else
+ gmtime(&skr,&tm_tmp);
#endif
- if (flag & 2)
+ 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,"%d-%02d-%02d",
+ 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 & 1)
- sprintf(strend(to)," %2d:%02d:%02d",
+ 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 & 4)
+ else if (flag & GETDATE_HHMMSSTIME)
sprintf(strend(to),"%02d%02d%02d",
start_time->tm_hour,
start_time->tm_min,
diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c
index d80de3101be..a55a2d81c2c 100644
--- a/mysys/mf_iocache.c
+++ b/mysys/mf_iocache.c
@@ -27,7 +27,7 @@
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
- flush_io_cache().
+ 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
@@ -43,7 +43,7 @@ TODO:
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 flush_io_cache() and
+ 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.
*/
@@ -171,7 +171,7 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
info->arg = 0;
info->alloced_buffer = 0;
info->buffer=0;
- info->seek_not_done= test(file >= 0);
+ info->seek_not_done= test(file >= 0 && seek_offset != my_tell(file, MYF(0)));
info->disk_writes= 0;
#ifdef THREAD
info->share=0;
@@ -184,8 +184,10 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize,
{ /* Assume file isn't growing */
if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
{
- /* Calculate end of file to not allocate to big buffers */
+ /* Calculate end of file to avoid allocating oversized buffers */
end_of_file=my_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 */
@@ -360,7 +362,7 @@ my_bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
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 && flush_io_cache(info))
+ 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 */
@@ -969,7 +971,7 @@ int _my_b_write(register IO_CACHE *info, const byte *Buffer, uint Count)
Buffer+=rest_length;
Count-=rest_length;
info->write_pos+=rest_length;
- if (flush_io_cache(info))
+ if (my_b_flush_io_cache(info,1))
return 1;
if (Count >= IO_SIZE)
{ /* Fill first intern buffer */
@@ -1212,6 +1214,7 @@ 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));
#ifdef THREAD
/*
@@ -1221,7 +1224,7 @@ int end_io_cache(IO_CACHE *info)
*/
if (info->share)
{
- pthread_cond_destroy (&info->share->cond);
+ pthread_cond_destroy(&info->share->cond);
pthread_mutex_destroy(&info->share->mutex);
info->share=0;
}
@@ -1236,7 +1239,7 @@ int end_io_cache(IO_CACHE *info)
{
info->alloced_buffer=0;
if (info->file != -1) /* File doesn't exist */
- error=flush_io_cache(info);
+ error= my_b_flush_io_cache(info,1);
my_free((gptr) info->buffer,MYF(MY_WME));
info->buffer=info->read_pos=(byte*) 0;
}
diff --git a/mysys/mf_iocache2.c b/mysys/mf_iocache2.c
index 3755bcdb53d..1f3db84304e 100644
--- a/mysys/mf_iocache2.c
+++ b/mysys/mf_iocache2.c
@@ -65,6 +65,13 @@ my_off_t my_b_append_tell(IO_CACHE* info)
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
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index cee1b7eb4e9..2308536cd37 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -341,8 +341,8 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
blocks--;
/* Allocate memory for cache page buffers */
if ((keycache->block_mem=
- my_malloc_lock((ulong) blocks * keycache->key_cache_block_size,
- MYF(0))))
+ my_large_malloc((ulong) blocks * keycache->key_cache_block_size,
+ MYF(MY_WME))))
{
/*
Allocate memory for blocks, hash_links and hash entries;
@@ -351,7 +351,7 @@ int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
if ((keycache->block_root= (BLOCK_LINK*) my_malloc((uint) length,
MYF(0))))
break;
- my_free_lock(keycache->block_mem, MYF(0));
+ my_large_free(keycache->block_mem, MYF(0));
keycache->block_mem= 0;
}
if (blocks < 8)
@@ -422,7 +422,7 @@ err:
keycache->blocks= 0;
if (keycache->block_mem)
{
- my_free_lock((gptr) keycache->block_mem, MYF(0));
+ my_large_free((gptr) keycache->block_mem, MYF(0));
keycache->block_mem= NULL;
}
if (keycache->block_root)
@@ -606,7 +606,7 @@ void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
{
if (keycache->block_mem)
{
- my_free_lock((gptr) keycache->block_mem, MYF(0));
+ my_large_free((gptr) keycache->block_mem, MYF(0));
keycache->block_mem= NULL;
my_free((gptr) keycache->block_root, MYF(0));
keycache->block_root= NULL;
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index d8c19d86e5c..e0d6288f76b 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -166,7 +166,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
gptr point;
reg1 USED_MEM *next= 0;
reg2 USED_MEM **prev;
-
+ DBUG_ENTER("alloc_root");
+ DBUG_PRINT("enter",("root: 0x%lx", mem_root));
DBUG_ASSERT(alloc_root_inited(mem_root));
Size= ALIGN_SIZE(Size);
@@ -213,7 +214,8 @@ gptr alloc_root(MEM_ROOT *mem_root,unsigned int Size)
mem_root->used= next;
mem_root->first_block_usage= 0;
}
- return(point);
+ DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point));
+ DBUG_RETURN(point);
#endif
}
@@ -245,6 +247,19 @@ static inline void mark_blocks_free(MEM_ROOT* root)
/*
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.
*/
void free_root(MEM_ROOT *root, myf MyFlags)
diff --git a/mysys/my_bit.c b/mysys/my_bit.c
index 55dd72f5f76..01c9b5ea68d 100644
--- a/mysys/my_bit.c
+++ b/mysys/my_bit.c
@@ -71,3 +71,8 @@ uint my_count_bits(ulonglong v)
#endif
}
+uint my_count_bits_ushort(ushort v)
+{
+ return nbits[v];
+}
+
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c
index f0d3339535d..c0eb6f15548 100644
--- a/mysys/my_bitmap.c
+++ b/mysys/my_bitmap.c
@@ -29,6 +29,9 @@
* bitmap_intersect() is an exception :)
(for for Bitmap::intersect(ulonglong map2buff))
+ If THREAD is defined all bitmap operations except bitmap_init/bitmap_free
+ are thread-safe.
+
TODO:
Make assembler THREAD safe versions of these using test-and-set instructions
*/
@@ -37,7 +40,7 @@
#include <my_bitmap.h>
#include <m_string.h>
-static inline void bitmap_lock(MY_BITMAP* map)
+static inline void bitmap_lock(MY_BITMAP *map)
{
#ifdef THREAD
if (map->mutex)
@@ -45,7 +48,7 @@ static inline void bitmap_lock(MY_BITMAP* map)
#endif
}
-static inline void bitmap_unlock(MY_BITMAP* map)
+static inline void bitmap_unlock(MY_BITMAP *map)
{
#ifdef THREAD
if (map->mutex)
@@ -327,3 +330,66 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
bitmap_unlock(map);
}
+
+/*
+ SYNOPSIS
+ bitmap_bits_set()
+ map
+ RETURN
+ Number of set bits in the bitmap.
+*/
+
+uint bitmap_bits_set(const MY_BITMAP *map)
+{
+ uchar *m= map->bitmap;
+ uchar *end= m + map->bitmap_size;
+ uint res= 0;
+
+ DBUG_ASSERT(map->bitmap);
+ bitmap_lock((MY_BITMAP *)map);
+ while (m < end)
+ {
+ res+= my_count_bits_ushort(*m++);
+ }
+ bitmap_unlock((MY_BITMAP *)map);
+ return res;
+}
+
+
+/*
+ SYNOPSIS
+ bitmap_get_first()
+ map
+ RETURN
+ Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set.
+*/
+
+uint bitmap_get_first(const MY_BITMAP *map)
+{
+ uchar *bitmap=map->bitmap;
+ uint bit_found = MY_BIT_NONE;
+ uint bitmap_size=map->bitmap_size*8;
+ uint i;
+
+ DBUG_ASSERT(map->bitmap);
+ bitmap_lock((MY_BITMAP *)map);
+ for (i=0; i < bitmap_size ; i++, bitmap++)
+ {
+ if (*bitmap != 0xff)
+ { /* Found slot with free bit */
+ uint b;
+ for (b=0; ; b++)
+ {
+ if (!(*bitmap & (1 << b)))
+ {
+ bit_found = (i*8)+b;
+ break;
+ }
+ }
+ break; /* Found bit */
+ }
+ }
+ bitmap_unlock((MY_BITMAP *)map);
+ return bit_found;
+}
+
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index cf26428d65f..9760de29a08 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -30,7 +30,9 @@
MyFlags Flags
DESCRIPTION
- my_chsize() truncates file if shorter else fill with the filler character
+ 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
@@ -48,9 +50,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));
if (oldsize > newlength)
+ {
#if defined(HAVE_SETFILEPOINTER)
/* This is for the moment only true on windows */
- {
long is_success;
HANDLE win_file= (HANDLE) _get_osfhandle(fd);
long length_low, length_high;
@@ -63,35 +65,29 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_RETURN(0);
my_errno= GetLastError();
goto err;
- }
#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
*/
VOID(my_seek(fd, newlength, MY_SEEK_SET, MYF(MY_WME+MY_FAE)));
swap_variables(my_off_t, newlength, oldsize);
- }
#endif
+ }
/* Full file with 'filler' until it's as big as requested */
bfill(buff, IO_SIZE, filler);
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 8a377f63c7e..0c18bbf6e8b 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -22,10 +22,40 @@
/* Define some external variables for error handling */
-const char ** NEAR my_errmsg[MAXMAPS]={0,0,0,0};
+/*
+ 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), ...)
+*/
+
char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
/*
+ 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 **meh_errmsgs; /* error messages array */
+ int meh_first; /* error number matching array slot 0 */
+ int meh_last; /* error number matching last slot */
+} my_errmsgs_globerrs = {NULL, globerrs, EE_ERROR_FIRST, EE_ERROR_LAST};
+static struct my_err_head *my_errmsgs_list= &my_errmsgs_globerrs;
+
+/*
Error message to user
SYNOPSIS
@@ -33,115 +63,42 @@ char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
nr Errno
MyFlags Flags
... variable list
- NOTE
- The following subset of printf format is supported:
- "%[0-9.-]*l?[sdu]", where all length flags are parsed but ignored.
- Additionally "%.*s" is supported and "%.*[ud]" is correctly parsed but
- the length value is ignored.
+ RETURN
+ What (*error_handler_hook)() returns:
+ 0 OK
*/
-int my_error(int nr,myf MyFlags, ...)
+int my_error(int nr, myf MyFlags, ...)
{
- va_list ap;
- uint olen, plen;
- reg1 const char *tpos;
- reg2 char *endpos;
- char * par;
- char ebuff[ERRMSGSIZE+20];
- int prec_chars; /* output precision */
- my_bool prec_supplied;
+ const char *format;
+ struct my_err_head *meh_p;
+ va_list args;
+ char ebuff[ERRMSGSIZE + 20];
DBUG_ENTER("my_error");
- LINT_INIT(prec_chars); /* protected by prec_supplied */
- va_start(ap,MyFlags);
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno));
- if (nr / ERRMOD == GLOB && my_errmsg[GLOB] == 0)
- init_glob_errs();
+ /* 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;
- olen=(uint) strlen(tpos=my_errmsg[nr / ERRMOD][nr % ERRMOD]);
- endpos=ebuff;
+#ifdef SHARED_LIBRARY
+ if ((meh_p == &my_errmsgs_globerrs) && ! globerrs[0])
+ init_glob_errs();
+#endif
- while (*tpos)
+ /* 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)
+ (void) my_snprintf (ebuff, sizeof(ebuff), "Unknown error %d", nr);
+ else
{
- if (tpos[0] != '%')
- {
- *endpos++= *tpos++; /* Copy ordinary char */
- continue;
- }
- if (*++tpos == '%') /* test if %% */
- {
- olen--;
- }
- else
- {
- /*
- Skip size/precision flags to be compatible with printf.
- The only size/precision flag supported is "%.*s".
- If "%.*u" or "%.*d" are encountered, the precision number is read
- from the variable argument list but its value is ignored.
- */
- prec_supplied= 0;
- if (*tpos== '.')
- {
- tpos++;
- olen--;
- if (*tpos == '*')
- {
- tpos++;
- olen--;
- prec_chars= va_arg(ap, int); /* get length parameter */
- prec_supplied= 1;
- }
- }
-
- if (!prec_supplied)
- {
- while (my_isdigit(&my_charset_latin1, *tpos) || *tpos == '.' ||
- *tpos == '-')
- tpos++;
-
- if (*tpos == 'l') /* Skip 'l' argument */
- tpos++;
- }
-
- if (*tpos == 's') /* String parameter */
- {
- par= va_arg(ap, char *);
- plen= (uint) strlen(par);
- if (prec_supplied && prec_chars > 0)
- plen= min((uint)prec_chars, plen);
- if (olen + plen < ERRMSGSIZE+2) /* Replace if possible */
- {
- strmake(endpos, par, plen);
- endpos+= plen;
- tpos++;
- olen+= plen-2;
- continue;
- }
- }
- else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */
- {
- register int iarg;
- iarg= va_arg(ap, int);
- if (*tpos == 'd')
- plen= (uint) (int10_to_str((long) iarg, endpos, -10) - endpos);
- else
- plen= (uint) (int10_to_str((long) (uint) iarg, endpos, 10) - endpos);
- if (olen + plen < ERRMSGSIZE+2) /* Replace parameter if possible */
- {
- endpos+= plen;
- tpos++;
- olen+= plen-2;
- continue;
- }
- }
- }
- *endpos++= '%'; /* % used as % or unknown code */
+ va_start(args,MyFlags);
+ (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
+ va_end(args);
}
- *endpos= '\0'; /* End of errmessage */
- va_end(ap);
DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags));
}
@@ -160,11 +117,14 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
+ 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) vsprintf (ebuff,format,args);
+ (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
va_end(args);
- return (*error_handler_hook)(error, ebuff, MyFlags);
+ DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags));
}
/*
@@ -181,3 +141,109 @@ int my_message(uint error, const char *str, register myf MyFlags)
{
return (*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 **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->meh_errmsgs= 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))
+ 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->meh_errmsgs;
+ my_free((gptr) meh_p, MYF(0));
+
+ return errmsgs;
+}
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 53e46932167..5e93ad56cb5 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -205,7 +205,8 @@ int handle_options(int *argc, char ***argv,
{
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]] == '-' ||
+ opt_str[special_opt_prefix_lengths[i]] == '_'))
{
/*
We were called with a special prefix, we can reuse opt_found
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 5ee181ca78e..87e526d0ea3 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -21,11 +21,11 @@ int mi_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 (skip_end_space)
+ if (!part_key)
return charset_info->coll->strnncollsp(charset_info, a, a_length,
- b, b_length);
+ b, b_length, !skip_end_space);
return charset_info->coll->strnncoll(charset_info, a, a_length,
- b, b_length, part_key);
+ b, b_length, part_key);
}
@@ -178,6 +178,7 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
}
break;
case HA_KEYTYPE_BINARY:
+ case HA_KEYTYPE_BIT:
if (keyseg->flag & HA_SPACE_PACK)
{
int a_length,b_length,pack_length;
@@ -206,13 +207,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
b+=length;
}
break;
- case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARTEXT1:
+ case HA_KEYTYPE_VARTEXT2:
{
- int a_length,full_a_length,b_length,full_b_length,pack_length;
+ int a_length,b_length,pack_length;
get_key_length(a_length,a);
get_key_pack_length(b_length,pack_length,b);
- full_a_length= a_length;
- full_b_length= b_length;
next_key_length=key_length-b_length-pack_length;
if (piks &&
@@ -221,14 +221,17 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
next_key_length <= 0),
(my_bool) ((nextflag & (SEARCH_FIND |
SEARCH_UPDATE)) ==
- SEARCH_FIND))))
+ SEARCH_FIND &&
+ ! (keyseg->flag &
+ HA_END_SPACE_ARE_EQUAL)))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+= full_a_length;
- b+= full_b_length;
+ a+= a_length;
+ b+= b_length;
break;
}
break;
- case HA_KEYTYPE_VARBINARY:
+ case HA_KEYTYPE_VARBINARY1:
+ case HA_KEYTYPE_VARBINARY2:
{
int a_length,b_length,pack_length;
get_key_length(a_length,a);
diff --git a/mysys/my_largepage.c b/mysys/my_largepage.c
new file mode 100644
index 00000000000..0639c360b46
--- /dev/null
+++ b/mysys/my_largepage.c
@@ -0,0 +1,167 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 gptr my_large_malloc_int(uint size, myf my_flags);
+static my_bool my_large_free_int(gptr ptr, myf my_flags);
+
+/* 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
+*/
+
+gptr my_large_malloc(uint size, myf my_flags)
+{
+ gptr 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(gptr ptr, myf my_flags __attribute__((unused)))
+{
+ 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_flags))
+ my_free_lock(ptr, my_flags);
+
+ 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)
+{
+ FILE *f;
+ uint size = 0;
+ char buf[256];
+ DBUG_ENTER("my_get_large_page_size_int");
+
+ if (!(f = my_fopen("/proc/meminfo", O_RDONLY, MYF(MY_WME))))
+ goto finish;
+
+ while (fgets(buf, sizeof(buf), f))
+ if (sscanf(buf, "Hugepagesize: %u kB", &size))
+ break;
+
+ my_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 */
+
+gptr my_large_malloc_int(uint size, myf my_flags)
+{
+ int shmid;
+ gptr ptr;
+ struct shmid_ds buf;
+ DBUG_ENTER("my_large_malloc_int");
+
+ /* Align block size to my_large_page_size */
+ size = ((size - 1) & ~(my_large_page_size - 1)) + my_large_page_size;
+
+ shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
+ if (shmid < 0)
+ {
+ if (my_flags & MY_WME)
+ fprintf(stderr,
+ "Warning: Failed to allocate %d bytes from HugeTLB memory."
+ " errno %d\n", size, errno);
+
+ DBUG_RETURN(NULL);
+ }
+
+ ptr = shmat(shmid, NULL, 0);
+ if (ptr == (void *)-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(byte *ptr, myf my_flags __attribute__((unused)))
+{
+ DBUG_ENTER("my_large_free_int");
+ DBUG_RETURN(shmdt(ptr) == 0);
+}
+#endif /* HAVE_DECL_SHM_HUGETLB */
+
+#endif /* HAVE_LARGE_PAGES */
diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c
new file mode 100644
index 00000000000..cd84630a761
--- /dev/null
+++ b/mysys/my_mmap.c
@@ -0,0 +1,91 @@
+/* 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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(__WIN__)
+
+static SECURITY_ATTRIBUTES mmap_security_attributes=
+ {sizeof(SECURITY_ATTRIBUTES), 0, TRUE};
+
+int my_getpagesize(void)
+{
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwPageSize;
+}
+
+void *my_mmap(void *addr, size_t len, int prot,
+ int flags, int fd, my_off_t offset)
+{
+ DWORD flProtect=0;
+ HANDLE hFileMap;
+ LPVOID ptr;
+ HANDLE hFile= (HANDLE)_get_osfhandle(fd);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return MAP_FAILED;
+
+ flProtect|=SEC_COMMIT;
+
+ hFileMap=CreateFileMapping(hFile, &mmap_security_attributes,
+ PAGE_READWRITE, 0, len, NULL);
+ if (hFileMap == 0)
+ return MAP_FAILED;
+
+ ptr=MapViewOfFile(hFileMap,
+ flags & 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)
+ return ptr;
+
+ return MAP_FAILED;
+}
+
+int my_munmap(void *addr, size_t len)
+{
+ 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/mysys/my_new.cc b/mysys/my_new.cc
index 14423c3afd5..66f3a14eeb4 100644
--- a/mysys/my_new.cc
+++ b/mysys/my_new.cc
@@ -45,5 +45,14 @@ void operator delete[] (void *ptr) throw ()
free(ptr);
}
+C_MODE_START
+
+int __cxa_pure_virtual() {
+ assert("Pure virtual method called." == "Aborted");
+ return 0;
+}
+
+C_MODE_END
+
#endif /* USE_MYSYS_NEW */
diff --git a/mysys/my_open.c b/mysys/my_open.c
index 7cf40b57403..69d63c49554 100644
--- a/mysys/my_open.c
+++ b/mysys/my_open.c
@@ -79,7 +79,7 @@ File my_open(const char *FileName, int Flags, myf MyFlags)
my_close()
fd File sescriptor
myf Special Flags
-
+
*/
int my_close(File fd, myf MyFlags)
@@ -89,7 +89,12 @@ int my_close(File fd, myf MyFlags)
DBUG_PRINT("my",("fd: %d MyFlags: %d",fd, MyFlags));
pthread_mutex_lock(&THR_LOCK_open);
- if ((err = close(fd)))
+ do
+ {
+ err= close(fd);
+ } while (err == -1 && errno == EINTR);
+
+ if (err)
{
DBUG_PRINT("error",("Got error %d on close",err));
my_errno=errno;
diff --git a/mysys/my_static.c b/mysys/my_static.c
index 5f034555156..8207463ea50 100644
--- a/mysys/my_static.c
+++ b/mysys/my_static.c
@@ -25,6 +25,8 @@
#include "my_alarm.h"
#endif
+my_bool timed_mutexes= 0;
+
/* from my_init */
my_string home_dir=0,my_progname=0;
char NEAR curr_dir[FN_REFLEN]= {0},
@@ -61,6 +63,12 @@ const char *soundex_map= "01230120022455012623010202";
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_tempnam */
#if !defined(HAVE_TEMPNAM) || defined(HPUX11)
int _my_tempnam_used=0;
diff --git a/mysys/my_sync.c b/mysys/my_sync.c
index 317ca039346..c557324b52c 100644
--- a/mysys/my_sync.c
+++ b/mysys/my_sync.c
@@ -27,7 +27,14 @@
my_flags Flags (now only MY_WME is supported)
NOTE
- If file system supports its, only file data is synced, not inode date
+ 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
@@ -40,21 +47,30 @@ int my_sync(File fd, myf my_flags)
DBUG_ENTER("my_sync");
DBUG_PRINT("my",("Fd: %d my_flags: %d", fd, my_flags));
+ do
+ {
#if defined(HAVE_FDATASYNC)
- res= fdatasync(fd);
+ res= fdatasync(fd);
#elif defined(HAVE_FSYNC)
- res=fsync(fd);
+ res= fsync(fd);
#elif defined(__WIN__)
res= _commit(fd);
#else
- res= 0; /* No sync (strange OS) */
+ res= 0; /* No sync (strange OS) */
#endif
+ } while (res == -1 && errno == EINTR);
+
if (res)
{
- if (!(my_errno= errno))
- my_errno= -1; /* Unknown error */
- if (my_flags & MY_WME)
+ int er= errno;
+ if (!(my_errno= er))
+ my_errno= -1; /* Unknown error */
+ if ((my_flags & MY_IGNORE_BADFD) &&
+ (er == EBADF || er == EINVAL || er == EROFS))
+ 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_read */
+} /* my_sync */
+
diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c
index 878e1f6bfc6..4d23d01cd82 100644
--- a/mysys/my_thr_init.c
+++ b/mysys/my_thr_init.c
@@ -67,12 +67,11 @@ my_bool my_thread_global_init(void)
/*
Set mutex type to "fast" a.k.a "adaptive"
- The mutex kind determines what happens if a thread attempts to lock
- a mutex it already owns with pthread_mutex_lock(3). If the mutex
- is of the ``fast'' kind, pthread_mutex_lock(3) simply suspends
- the calling thread forever. If the mutex is of the ``error checking''
- kind, pthread_mutex_lock(3) returns immediately with the error
- code EDEADLK.
+ 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,
diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c
index 5fc7ccab4fa..57778574bb6 100644
--- a/mysys/ptr_cmp.c
+++ b/mysys/ptr_cmp.c
@@ -21,6 +21,7 @@
*/
#include "mysys_priv.h"
+#include <myisampack.h>
static int ptr_compare(uint *compare_length, uchar **a, uchar **b);
static int ptr_compare_0(uint *compare_length, uchar **a, uchar **b);
@@ -152,3 +153,41 @@ static int ptr_compare_3(uint *compare_length,uchar **a, uchar **b)
}
return (0);
}
+
+void my_store_ptr(byte *buff, uint 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(byte *ptr, uint 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) mi_uint2korr(ptr); break;
+ default: DBUG_ASSERT(0);
+ }
+ return pos;
+}
+
diff --git a/mysys/raid.cc b/mysys/raid.cc
index 20e70d2d102..a645c0109db 100644
--- a/mysys/raid.cc
+++ b/mysys/raid.cc
@@ -187,7 +187,7 @@ extern "C" {
uint my_raid_write(File fd,const byte *Buffer, uint Count, myf MyFlags)
{
DBUG_ENTER("my_raid_write");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
+ DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
fd, Buffer, Count, MyFlags));
if (is_raid(fd))
{
@@ -200,7 +200,7 @@ extern "C" {
uint my_raid_read(File fd, byte *Buffer, uint Count, myf MyFlags)
{
DBUG_ENTER("my_raid_read");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
+ DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
fd, Buffer, Count, MyFlags));
if (is_raid(fd))
{
@@ -214,8 +214,9 @@ extern "C" {
myf MyFlags)
{
DBUG_ENTER("my_raid_pread");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d",
- Filedes, Buffer, Count, offset, MyFlags));
+ DBUG_PRINT("enter",
+ ("Fd: %d Buffer: 0x%lx Count: %u offset: %u MyFlags: %d",
+ Filedes, Buffer, Count, offset, MyFlags));
if (is_raid(Filedes))
{
assert(offset != MY_FILEPOS_ERROR);
@@ -233,8 +234,9 @@ extern "C" {
my_off_t offset, myf MyFlags)
{
DBUG_ENTER("my_raid_pwrite");
- DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d",
- Filedes, Buffer, Count, offset, MyFlags));
+ DBUG_PRINT("enter",
+ ("Fd: %d Buffer: 0x %lx Count: %u offset: %u MyFlags: %d",
+ Filedes, Buffer, Count, offset, MyFlags));
if (is_raid(Filedes))
{
assert(offset != MY_FILEPOS_ERROR);
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index 19611a6027a..05d14073953 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -86,6 +86,7 @@ void init_thr_alarm(uint max_alarms)
{
struct sigaction sact;
sact.sa_flags = 0;
+ bzero((char*) &sact, sizeof(sact));
sact.sa_handler = thread_alarm;
sigaction(THR_CLIENT_ALARM, &sact, (struct sigaction*) 0);
}
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index d47ca8de183..7761d2a9fc8 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -409,7 +409,7 @@ static my_bool wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
result=0;
statistic_increment(locks_waited, &THR_LOCK_lock);
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
check_locks(data->lock,"got wait_for_lock",0);
}
pthread_mutex_unlock(&data->lock->mutex);
@@ -468,7 +468,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
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);
+ (*lock->get_status)(data->status_param, 0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
@@ -489,7 +489,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
data->prev=lock->read.last;
lock->read.last= &data->next;
if (lock->get_status)
- (*lock->get_status)(data->status_param);
+ (*lock->get_status)(data->status_param, 0);
if ((int) lock_type == (int) TL_READ_NO_INSERT)
lock->read_no_write_count++;
check_locks(lock,"read lock with no write locks",0);
@@ -523,8 +523,10 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
data->prev=lock->write_wait.last;
lock->write_wait.last= &data->next;
data->cond=get_cond();
- if (lock->get_status)
- (*lock->get_status)(data->status_param);
+ /*
+ 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;
}
@@ -565,7 +567,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
lock->write.last= &data->next;
check_locks(lock,"second write lock",0);
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
statistic_increment(locks_immediate,&THR_LOCK_lock);
goto end;
}
@@ -578,9 +580,16 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
(ulong) lock->write_wait.data));
if (!lock->write_wait.data)
{ /* no scheduled write locks */
- if (lock_type == TL_WRITE_CONCURRENT_INSERT &&
- (*lock->check_status)(data->status_param))
- data->type=lock_type= thr_upgraded_concurrent_insert_lock;
+ 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 &&
@@ -592,7 +601,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
data->prev=lock->write.last;
lock->write.last= &data->next;
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*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;
@@ -1031,7 +1040,7 @@ my_bool thr_upgrade_write_delay_lock(THR_LOCK_DATA *data)
if (!lock->read.data) /* No read locks */
{ /* We have the lock */
if (data->lock->get_status)
- (*data->lock->get_status)(data->status_param);
+ (*data->lock->get_status)(data->status_param, 0);
pthread_mutex_unlock(&lock->mutex);
DBUG_RETURN(0);
}
@@ -1219,7 +1228,8 @@ static ulong sum=0;
/* The following functions is for WRITE_CONCURRENT_INSERT */
-static void test_get_status(void* param __attribute__((unused)))
+static void test_get_status(void* param __attribute__((unused)),
+ int concurrent_insert __attribute__((unused)))
{
}