diff options
-rw-r--r-- | .bzrignore | 1 | ||||
-rw-r--r-- | include/my_sys.h | 2 | ||||
-rw-r--r-- | mysys/Makefile.am | 7 | ||||
-rw-r--r-- | mysys/my_gethwaddr.c | 130 | ||||
-rw-r--r-- | sql/item_create.cc | 11 | ||||
-rw-r--r-- | sql/item_create.h | 1 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 109 | ||||
-rw-r--r-- | sql/item_strfunc.h | 22 | ||||
-rw-r--r-- | sql/lex.h | 3 | ||||
-rw-r--r-- | sql/mysql_priv.h | 12 | ||||
-rw-r--r-- | sql/mysqld.cc | 3 | ||||
-rw-r--r-- | sql/sql_class.cc | 8 |
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); } } |