summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--include/my_sys.h2
-rw-r--r--mysys/Makefile.am7
-rw-r--r--mysys/my_gethwaddr.c130
-rw-r--r--sql/item_create.cc11
-rw-r--r--sql/item_create.h1
-rw-r--r--sql/item_strfunc.cc109
-rw-r--r--sql/item_strfunc.h22
-rw-r--r--sql/lex.h3
-rw-r--r--sql/mysql_priv.h12
-rw-r--r--sql/mysqld.cc3
-rw-r--r--sql/sql_class.cc8
12 files changed, 288 insertions, 21 deletions
diff --git a/.bzrignore b/.bzrignore
index fbc25f32f7a..541e854b188 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -646,3 +646,4 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
+mysys/test_gethwaddr
diff --git a/include/my_sys.h b/include/my_sys.h
index 9254f29ee72..6547022601d 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -739,6 +739,8 @@ extern ulong crc32(ulong crc, const uchar *buf, uint len);
extern uint my_set_max_open_files(uint files);
void my_free_open_file_info(void);
+my_bool my_gethwaddr(uchar *to);
+
/* character sets */
extern uint get_charset_number(const char *cs_name, uint cs_flags);
extern uint get_collation_number(const char *name);
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index eb6d21c360a..77b17d28ba3 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -39,7 +39,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.c \
mf_pack.c mf_unixpath.c mf_strip.c \
- mf_wcomp.c mf_wfile.c \
+ mf_wcomp.c mf_wfile.c my_gethwaddr.c \
mf_qsort.c mf_qsort2.c mf_sort.c \
ptr_cmp.c mf_radix.c queues.c \
tree.c list.c hash.c array.c string.c typelib.c \
@@ -110,5 +110,10 @@ charset2html$(EXEEXT): charset2html.c $(LIBRARIES)
testhash$(EXEEXT): testhash.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS)
+test_gethwaddr$(EXEEXT): my_gethwaddr.c $(LIBRARIES)
+ $(CP) $(srcdir)/my_gethwaddr.c ./test_gethwaddr.c
+ $(LINK) $(FLAGS) -DMAIN ./test_gethwaddr.c $(LDADD) $(LIBS)
+ $(RM) -f ./test_gethwaddr.c
+
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c
new file mode 100644
index 00000000000..72f1cb975c4
--- /dev/null
+++ b/mysys/my_gethwaddr.c
@@ -0,0 +1,130 @@
+/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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 */
+
+/* get hardware address for an interface */
+/* if there are many available, any non-zero one can be used */
+
+#include "mysys_priv.h"
+#include <m_string.h>
+
+#ifndef MAIN
+static my_bool memcpy_and_test(uchar *to, uchar *from, uint len)
+{
+ uint i, res=1;
+
+ for (i=0; i < len; i++)
+ if ((*to++= *from++))
+ res=0;
+ return res;
+}
+
+#ifdef __FreeBSD__
+
+#include <net/ethernet.h>
+#include <sys/sysctl.h>
+#include <net/route.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+
+my_bool my_gethwaddr(uchar *to)
+{
+ size_t len;
+ uchar *buf, *next, *end, *addr;
+ struct if_msghdr *ifm;
+ struct sockaddr_dl *sdl;
+ int i, res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0};
+
+ if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1)
+ goto err;
+ if (!(buf = alloca(len)))
+ goto err;
+ if (sysctl(mib, 6, buf, &len, NULL, 0) < 0)
+ goto err;
+
+ end = buf + len;
+
+ for (next = buf ; res && next < end ; next += ifm->ifm_msglen)
+ {
+ ifm = (struct if_msghdr *)next;
+ if (ifm->ifm_type == RTM_IFINFO)
+ {
+ sdl = (struct sockaddr_dl *)(ifm + 1);
+ addr=LLADDR(sdl);
+ res=memcpy_and_test(to, addr, ETHER_ADDR_LEN);
+ }
+ }
+
+err:
+ return res;
+}
+
+#elif __linux__
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <net/ethernet.h>
+
+my_bool my_gethwaddr(uchar *to)
+{
+ int fd, res=1;
+ struct ifreq ifr;
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0)
+ goto err;
+
+ bzero(&ifr, sizeof(ifr));
+ strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
+
+ do {
+ if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0)
+ res=memcpy_and_test(to, (uchar *)&ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+ } while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6');
+
+ close(fd);
+err:
+ return res;
+}
+
+#else
+/* just fail */
+my_bool my_gethwaddr(uchar *to __attribute__((unused)))
+{
+ return 1;
+}
+#endif
+
+#else MAIN
+int main(int argc __attribute__((unused)),char **argv)
+{
+ uchar mac[6];
+ uint i;
+ MY_INIT(argv[0]);
+ if (my_gethwaddr(mac))
+ {
+ printf("my_gethwaddr failed with errno %d\n", errno);
+ exit(1);
+ }
+ for (i=0; i < sizeof(mac); i++)
+ {
+ if (i) printf(":");
+ printf("%02x", mac[i]);
+ }
+ printf("\n");
+ return 0;
+}
+#endif
+
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 4ed8182305d..eda3d43afdc 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -34,14 +34,14 @@ Item *create_func_acos(Item* a)
Item *create_func_aes_encrypt(Item* a, Item* b)
{
- return new Item_func_aes_encrypt(a, b);
+ return new Item_func_aes_encrypt(a, b);
}
-
+
Item *create_func_aes_decrypt(Item* a, Item* b)
{
return new Item_func_aes_decrypt(a, b);
}
-
+
Item *create_func_ascii(Item* a)
{
return new Item_func_ascii(a);
@@ -426,6 +426,11 @@ Item *create_func_ucase(Item* a)
return new Item_func_ucase(a);
}
+Item *create_func_uuid(void)
+{
+ return new Item_func_uuid();
+}
+
Item *create_func_version(void)
{
return new Item_string(NullS,server_version,
diff --git a/sql/item_create.h b/sql/item_create.h
index 773fdffbaf2..a6a3c9e1841 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -92,6 +92,7 @@ Item *create_func_time_format(Item *a, Item *b);
Item *create_func_time_to_sec(Item* a);
Item *create_func_to_days(Item* a);
Item *create_func_ucase(Item* a);
+Item *create_func_uuid(void);
Item *create_func_version(void);
Item *create_func_weekday(Item* a);
Item *create_load_file(Item* a);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index ed6e44262c7..bd21e38479c 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -2632,3 +2632,112 @@ err:
return 0;
}
#endif
+
+/*
+ UUID, as in
+ DCE 1.1: Remote Procedure Call,
+ Open Group Technical Standard Document Number C706, August 1997,
+ (supersedes C309 DCE: Remote Procedure Call 8/1994,
+ which was basis for ISO/IEC 11578:1996 specification)
+*/
+
+static struct rand_struct uuid_rand;
+static uint nanoseq;
+static ulonglong uuid_time=0;
+static char clock_seq_and_node_str[]="-0000-000000000000";
+
+/* we cannot use _dig_vec[] as letters should be lowercase */
+static const char hex[] = "0123456789abcdef";
+
+/* number of 100-nanosecond intervals between
+ 1582-10-15 00:00:00.00 and 1970-01-01 00:00:00.00 */
+#define UUID_TIME_OFFSET ((ulonglong) 141427 * 24 * 60 * 60 * 1000 * 10 )
+
+#define UUID_VERSION 0x1000
+#define UUID_VARIANT 0x8000
+
+static ulonglong get_uuid_time()
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ return (ulonglong)tv.tv_sec*10000000 +
+ (ulonglong)tv.tv_usec*10 + UUID_TIME_OFFSET + nanoseq;
+}
+
+static void tohex(char *to, uint from, uint len)
+{
+ to+= len;
+ while (len--)
+ {
+ *--to= hex[from & 15];
+ from >>= 4;
+ }
+}
+
+static void set_clock_seq_str()
+{
+ uint16 clock_seq= ((uint)(my_rnd(&uuid_rand)*16383)) | UUID_VARIANT;
+ tohex(clock_seq_and_node_str+1, clock_seq, 4);
+ nanoseq= 0;
+}
+
+String *Item_func_uuid::val_str(String *str)
+{
+ char *s;
+ pthread_mutex_lock(&LOCK_uuid_generator);
+ if (! uuid_time) /* first UUID() call. initializing data */
+ {
+ ulong tmp=sql_rnd_with_mutex();
+ uchar mac[6];
+ int i;
+ if (my_gethwaddr(mac))
+ {
+ /*
+ generating random "hardware addr"
+ and because specs explicitly specify that it should NOT correlate
+ with a clock_seq value (initialized random below), we use a separate
+ randominit() here
+ */
+ randominit(&uuid_rand, tmp + (ulong)current_thd, tmp + query_id);
+ for (i=0; i < sizeof(mac); i++)
+ mac[i]=(uchar)(my_rnd(&uuid_rand)*255);
+ }
+ s=clock_seq_and_node_str+sizeof(clock_seq_and_node_str)-1;
+ for (i=sizeof(mac)-1 ; i>=0 ; i--)
+ {
+ *--s=hex[mac[i] & 15];
+ *--s=hex[mac[i] >> 4];
+ }
+ randominit(&uuid_rand, tmp + (ulong)start_time, tmp + bytes_sent);
+ set_clock_seq_str();
+ }
+
+ ulonglong tv=get_uuid_time();
+ if (unlikely(tv < uuid_time))
+ set_clock_seq_str();
+ else
+ if (unlikely(tv == uuid_time))
+ { /* special protection from low-res system clocks */
+ nanoseq++;
+ tv++;
+ }
+ else
+ nanoseq=0;
+ uuid_time=tv;
+ pthread_mutex_unlock(&LOCK_uuid_generator);
+
+ uint32 time_low= tv & 0xFFFFFFFF;
+ uint16 time_mid= (tv >> 32) & 0xFFFF;
+ uint16 time_hi_and_version= (tv >> 48) | UUID_VERSION;
+
+ str->realloc(UUID_LENGTH+1);
+ str->length(UUID_LENGTH);
+ s=(char *) str->ptr();
+ s[8]=s[13]='-';
+ tohex(s, time_low, 8);
+ tohex(s+9, time_mid, 4);
+ tohex(s+14, time_hi_and_version, 4);
+ strmov(s+18, clock_seq_and_node_str);
+ return str;
+}
+
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 4832ddbd1b1..859983f443d 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -153,7 +153,7 @@ class Item_str_conv :public Item_str_func
public:
Item_str_conv(Item *item) :Item_str_func(item) {}
void fix_length_and_dec()
- {
+ {
collation.set(args[0]->collation);
max_length = args[0]->max_length;
}
@@ -589,10 +589,10 @@ public:
Item_func_quote(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "quote"; }
String *val_str(String *);
- void fix_length_and_dec()
- {
+ void fix_length_and_dec()
+ {
collation.set(args[0]->collation);
- max_length= args[0]->max_length * 2 + 2;
+ max_length= args[0]->max_length * 2 + 2;
}
};
@@ -600,7 +600,7 @@ class Item_func_conv_charset :public Item_str_func
{
CHARSET_INFO *conv_charset;
public:
- Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
+ Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a)
{ conv_charset=cs; }
String *val_str(String *);
void fix_length_and_dec();
@@ -625,7 +625,7 @@ public:
Item_func_charset(Item *a) :Item_str_func(a) {}
String *val_str(String *);
const char *func_name() const { return "charset"; }
- void fix_length_and_dec()
+ void fix_length_and_dec()
{
collation.set(system_charset_info);
max_length= 64 * collation.collation->mbmaxlen; // should be enough
@@ -691,3 +691,13 @@ public:
String *val_str(String *) ZLIB_DEPENDED_FUNCTION
};
+#define UUID_LENGTH (8+1+4+1+4+1+4+1+12)
+class Item_func_uuid: public Item_str_func
+{
+public:
+ Item_func_uuid(): Item_str_func() {}
+ void fix_length_and_dec() {max_length= UUID_LENGTH; }
+ const char *func_name() const{ return "uuid"; }
+ String *val_str(String *);
+};
+
diff --git a/sql/lex.h b/sql/lex.h
index 029a8ac4218..9cdb1067d91 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -654,7 +654,7 @@ static SYMBOL sql_functions[] = {
{ "STDDEV", SYM(STD_SYM)},
{ "STR_TO_DATE", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_str_to_date)},
{ "STRCMP", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_strcmp)},
- { "SUBSTR", SYM(SUBSTRING)},
+ { "SUBSTR", SYM(SUBSTRING)},
{ "SUBSTRING", SYM(SUBSTRING)},
{ "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX)},
{ "SUBTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
@@ -674,6 +674,7 @@ static SYMBOL sql_functions[] = {
{ "UNIQUE_USERS", SYM(UNIQUE_USERS)},
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP)},
{ "UPPER", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
+ { "UUID", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_uuid)},
{ "VARIANCE", SYM(VARIANCE_SYM)},
{ "VERSION", F_SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM)},
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index f5031f926af..535c1cb16be 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -802,7 +802,7 @@ extern char log_error_file[FN_REFLEN];
extern double log_10[32];
extern ulonglong keybuff_size;
extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
-extern ulong created_tmp_tables, created_tmp_disk_tables;
+extern ulong created_tmp_tables, created_tmp_disk_tables, bytes_sent;
extern ulong aborted_threads,aborted_connects;
extern ulong delayed_insert_timeout;
extern ulong delayed_insert_limit, delayed_queue_size;
@@ -857,7 +857,7 @@ extern FILE *bootstrap_file;
extern pthread_key(MEM_ROOT*,THR_MALLOC);
extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
- LOCK_error_log, LOCK_delayed_insert,
+ LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
LOCK_slave_list, LOCK_active_mi, LOCK_manager,
LOCK_global_system_variables, LOCK_user_conn;
@@ -1085,6 +1085,14 @@ inline const char *table_case_name(HA_CREATE_INFO *info, const char *name)
return ((lower_case_table_names == 2 && info->alias) ? info->alias : name);
}
+inline ulong sql_rnd_with_mutex()
+{
+ pthread_mutex_lock(&LOCK_thread_count);
+ ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
+ pthread_mutex_unlock(&LOCK_thread_count);
+ return tmp;
+}
+
Comp_creator *comp_eq_creator(bool invert);
Comp_creator *comp_ge_creator(bool invert);
Comp_creator *comp_gt_creator(bool invert);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 634f24203c4..07e07e97781 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -369,7 +369,7 @@ pthread_key(MEM_ROOT*,THR_MALLOC);
pthread_key(THD*, THR_THD);
pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_mapped_file, LOCK_status,
- LOCK_error_log,
+ LOCK_error_log, LOCK_uuid_generator,
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
LOCK_global_system_variables,
@@ -2206,6 +2206,7 @@ static int init_thread_environment()
(void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_active_mi, MY_MUTEX_INIT_FAST);
(void) pthread_mutex_init(&LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
+ (void) pthread_mutex_init(&LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
(void) my_rwlock_init(&LOCK_sys_init_connect, NULL);
(void) my_rwlock_init(&LOCK_sys_init_slave, NULL);
(void) my_rwlock_init(&LOCK_grant, NULL);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 9ed604033ab..6fe0521b07a 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -179,14 +179,8 @@ THD::THD():user_time(0), current_statement(0), is_fatal_error(0),
transaction.trans_log.end_of_file= max_binlog_cache_size;
}
#endif
- /*
- We need good random number initialization for new thread
- Just coping global one will not work
- */
{
- pthread_mutex_lock(&LOCK_thread_count);
- ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
- pthread_mutex_unlock(&LOCK_thread_count);
+ ulong tmp=sql_rnd_with_mutex();
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
}
}