diff --git a/include/config-win.h b/include/config-win.h index 475141a1989..ba1a987f14c 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -310,9 +310,6 @@ inline double ulonglong2double(ulonglong value) #define HAVE_SETFILEPOINTER #define HAVE_VIO -#define HAME_MMAP /* in mysys/my_mmap.c */ -#define HAVE_GETPAGESIZE /* in mysys/my_mmap.c */ - #ifdef NOT_USED #define HAVE_SNPRINTF /* Gave link error */ #define _snprintf snprintf diff --git a/include/my_sys.h b/include/my_sys.h index 9cce13e53dd..498a1bd30fe 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -796,7 +796,7 @@ void my_free_open_file_info(void); ulonglong my_getsystime(void); my_bool my_gethwaddr(uchar *to); -#ifdef HAVE_MMAP +#ifdef HAVE_SYS_MMAN_H #include <sys/mman.h> #ifndef MAP_NOSYNC @@ -815,6 +815,7 @@ my_bool my_gethwaddr(uchar *to); #define MAP_NOSYNC 0x0800 #define MAP_FAILED ((void *)-1) #define MS_SYNC 0x0000 +#define HAVE_MMAP int my_getpagesize(void); void *my_mmap(void *, size_t, int, int, int, my_off_t); diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index ee0047934ab..df117479814 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -111,10 +111,14 @@ insert into t1 values ("Alas"); /*!40019 SET @@session.max_insert_delayed_threads=0*/; ROLLBACK; use test; -SET TIMESTAMP=1065204671; +SET TIMESTAMP=1108844556; BEGIN; +SET TIMESTAMP=1108844555; +insert t1 values (1); /*!40019 SET @@session.max_insert_delayed_threads=0*/; use test; -SET TIMESTAMP=1065204671; +SET TIMESTAMP=1108844556; BEGIN; +SET TIMESTAMP=1108844555; +insert t1 values (1); drop table t1, t2; diff --git a/mysql-test/r/rpl_trunc_binlog.result b/mysql-test/r/rpl_trunc_binlog.result index 5eb5f810a8f..2663fffe4d4 100644 --- a/mysql-test/r/rpl_trunc_binlog.result +++ b/mysql-test/r/rpl_trunc_binlog.result @@ -6,8 +6,12 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; stop slave; flush logs; +create table t1 (a int) engine=bdb; reset slave; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 # # master-bin.000001 Yes No 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. A probable cause is that the master died while writing the transaction to its binary log. 0 79 # None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000002 4 # # master-bin.000002 Yes Yes 0 Rolling back unfinished transaction (no COMMIT or ROLLBACK) from relay log. A probable cause is that the master died while writing the transaction to its binary log. 0 4 # None 0 No # +select * from t1; +a +drop table t1; diff --git a/mysql-test/std_data/trunc_binlog.000001 b/mysql-test/std_data/trunc_binlog.000001 index 2c2b4ec6ce4..3da2490eab2 100644 Binary files a/mysql-test/std_data/trunc_binlog.000001 and b/mysql-test/std_data/trunc_binlog.000001 differ diff --git a/mysql-test/t/rpl_trunc_binlog.test b/mysql-test/t/rpl_trunc_binlog.test index b2e7e52f5e4..eec36532275 100644 --- a/mysql-test/t/rpl_trunc_binlog.test +++ b/mysql-test/t/rpl_trunc_binlog.test @@ -1,21 +1,28 @@ # We are testing if a binlog which contains BEGIN but not COMMIT (the -# master did while writing the transaction to the binlog) triggers an -# error on slave. So we use such a truncated binlog and simulate that +# master died while writing the transaction to the binlog) triggers a +# rollback on slave. So we use such a truncated binlog and simulate that # the master restarted after this. source include/master-slave.inc; connection slave; -# If we are not supporting transactions in the slave, the unfinished transaction -# won't cause any error, so we need to skip the test. In the 4.0 testsuite, the -# slave always runs without InnoDB, so we check for BDB. +# If we are not supporting transactions in the slave, the unfinished +# transaction won't cause any error, so we need to skip the test. In the 4.0 +# testsuite, the slave always runs without InnoDB, so we check for BDB. source include/have_bdb.inc; stop slave; + connection master; flush logs; system mv -f var/log/master-bin.000001 var/log/master-bin.000002; system cp std_data/trunc_binlog.000001 var/log/master-bin.000001; + connection slave; + +# truncated binlog contains: BEGIN; INSERT t1 VALUES (1); +# so let's create the table t1 on slave + +create table t1 (a int) engine=bdb; reset slave; start slave; # can't sync_with_master so we must sleep @@ -23,3 +30,6 @@ sleep 3; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 8 # 9 # 23 # 33 # show slave status; +select * from t1; +drop table t1; + diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c index 883181edd6c..0225e7fac24 100644 --- a/mysys/my_mmap.c +++ b/mysys/my_mmap.c @@ -16,7 +16,7 @@ #include "mysys_priv.h" -#ifdef HAVE_MMAP +#ifdef HAVE_SYS_MMAN_H /* system msync() only syncs mmap'ed area to fs cache. @@ -84,6 +84,6 @@ int my_msync(int fd, void *addr, size_t len, int flags) } #endif -#error "no mmap!" +#warning "no mmap!" #endif diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc index cb0780ea74d..d043a66e71a 100644 --- a/sql/examples/ha_example.cc +++ b/sql/examples/ha_example.cc @@ -414,7 +414,7 @@ int ha_example::rnd_next(byte *buf) position() is called after each call to rnd_next() if the data needs to be ordered. You can do something like the following to store the position: - ha_store_ptr(ref, ref_length, current_position); + my_store_ptr(ref, ref_length, current_position); The server uses ref to store data. ref_length in the above case is the size needed to store current_position. ref is just a byte array diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index 695c71677c0..518f59eb853 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -1503,7 +1503,7 @@ int ha_federated::rnd_next(byte *buf) /* 'position()' is called after each call to rnd_next() if the data needs to be ordered. You can do something like the following to store the position: - ha_store_ptr(ref, ref_length, current_position); + my_store_ptr(ref, ref_length, current_position); The server uses ref to store data. ref_length in the above case is the size needed to store current_position. ref is just a byte array that the server @@ -1516,7 +1516,7 @@ int ha_federated::rnd_next(byte *buf) void ha_federated::position(const byte *record) { DBUG_ENTER("ha_federated::position"); - //ha_store_ptr Add seek storage + //my_store_ptr Add seek storage *(MYSQL_ROW_OFFSET *)ref=current_position; // ref is always aligned DBUG_VOID_RETURN; } diff --git a/sql/log.cc b/sql/log.cc index cb776cff0e9..b048323aa76 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2415,6 +2415,7 @@ void sql_print_information(const char *format, ...) DBUG_VOID_RETURN; } +#ifdef HAVE_MMAP /********* transaction coordinator log for 2pc - mmap() based solution *******/ /* @@ -2460,10 +2461,6 @@ uint opt_tc_log_size=TC_LOG_MIN_SIZE; uint tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_page_waits=0, tc_log_cur_pages_used=0; -TC_LOG *tc_log; -TC_LOG_MMAP tc_log_mmap; -TC_LOG_DUMMY tc_log_dummy; - int TC_LOG_MMAP::open(const char *opt_name) { uint i; @@ -2473,12 +2470,8 @@ int TC_LOG_MMAP::open(const char *opt_name) DBUG_ASSERT(total_ha_2pc > 1); DBUG_ASSERT(opt_name && opt_name[0]); -#ifdef HAVE_GETPAGESIZE tc_log_page_size= my_getpagesize(); DBUG_ASSERT(TC_LOG_PAGE_SIZE % tc_log_page_size == 0); -#else - tc_log_page_size= TC_LOG_PAGE_SIZE; -#endif fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME); fd= my_open(logname, O_RDWR, MYF(0)); @@ -2861,6 +2854,11 @@ err1: "--tc-heuristic-recover={commit|rollback}"); return 1; } +#endif + +TC_LOG *tc_log; +TC_LOG_DUMMY tc_log_dummy; +TC_LOG_MMAP tc_log_mmap; /* Perform heuristic recovery, if --tc-heuristic-recover was used diff --git a/sql/sql_class.h b/sql/sql_class.h index 05fd1fdea58..34019e73f96 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -80,6 +80,7 @@ class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging void unlog(ulong cookie, my_xid xid) { } }; +#ifdef HAVE_MMAP class TC_LOG_MMAP: public TC_LOG { private: @@ -103,7 +104,8 @@ class TC_LOG_MMAP: public TC_LOG char logname[FN_REFLEN]; File fd; - uint file_length, npages, inited; + my_off_t file_length; + uint npages, inited; uchar *data; struct st_page *pages, *syncing, *active, *pool, *pool_last; /* @@ -128,6 +130,9 @@ class TC_LOG_MMAP: public TC_LOG int sync(); int overflow(); }; +#else +#define TC_LOG_MMAP TC_LOG_DUMMY +#endif extern TC_LOG *tc_log; extern TC_LOG_MMAP tc_log_mmap; diff --git a/strings/decimal.c b/strings/decimal.c index 212bd7204f6..e6d2d9b14dd 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -14,7 +14,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#line __LINE__ "decimal.c" +#line 18 "decimal.c" /* ======================================================================= @@ -107,14 +107,29 @@ #include <m_string.h> #include <decimal.h> +/* + Internally decimal numbers are stored base 10^9 (see DIG_BASE below) + So one "decimal_digit" is + + 0 < decimal_digit <= DIG_MAX < DIG_BASE + + in the struct st_decimal: + + intg is the number of *decimal* digits (NOT number of decimal_digit's !) + before the point + frac - number of decimal digits after the point + buf is an array of decimal_digit's + len is the length of buf (length of allocated space) in decimal_digit's, + not in bytes +*/ typedef decimal_digit dec1; typedef longlong dec2; #define DIG_PER_DEC1 9 #define DIG_MASK 100000000 #define DIG_BASE 1000000000 -#define DIG_MAX 999999999 -#define DIG_BASE2 LL(1000000000000000000) +#define DIG_MAX (DIG_BASE-1) +#define DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE) #define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1) static const dec1 powers10[DIG_PER_DEC1+1]={ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; @@ -1073,6 +1088,68 @@ int decimal2longlong(decimal *from, longlong *to) RETURN VALUE E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW + + DESCRIPTION + for storage decimal numbers are converted to the "binary" format. + + This format has the following properties: + 1. length of the binary representation depends on the {precision, scale} + as provided by the caller and NOT on the intg/frac of the decimal to + convert. + 2. binary representations of the same {precision, scale} can be compared + with memcmp - with the same result as decimal_cmp() of the original + decimals (not taking into account possible precision loss during + conversion). + + This binary format is as follows: + 1. First the number is converted to have a requested precision and scale. + 2. Every full DIG_PER_DEC1 digits of intg part are stored in 4 bytes + as is + 3. The first intg % DIG_PER_DEC1 digits are stored in the reduced + number of bytes (enough bytes to store this number of digits - + see dig2bytes) + 4. same for frac - full decimal_digit's are stored as is, + the last frac % DIG_PER_DEC1 digits - in the reduced number of bytes. + 5. If the number is negative - every byte is inversed. + 5. The very first bit of the resulting byte array is inverted (because + memcmp compares unsigned bytes, see property 2 above) + + Example: + + 1234567890.1234 + + internally is represented as 3 decimal_digit's + + 1 234567890 123400000 + + (assuming we want a binary representation with precision=14, scale=4) + in hex it's + + 00-00-00-01 0D-FB-38-D2 07-5A-EF-40 + + now, middle decimal_digit is full - it stores 9 decimal digits. It goes + into binary representation as is: + + + ........... 0D-FB-38-D2 ............ + + First decimal_digit has only one decimal digit. We can store one digit in + one byte, no need to waste four: + + 01 0D-FB-38-D2 ............ + + now, last digit. It's 123400000. We can store 1234 in two bytes: + + 01 0D-FB-38-D2 04-D2 + + So, we've packed 12 bytes number in 7 bytes. + And now we invert the highest bit to get the final result: + + 81 0D FB 38 D2 04 D2 + + And for -1234567890.1234 it would be + + 7E F2 04 37 2D FB 2D */ int decimal2bin(decimal *from, char *to, int precision, int frac) { @@ -1415,6 +1492,11 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode else *(++buf1)=DIG_BASE; } + else if (frac0+intg0==0) + { + decimal_make_zero(to); + return E_DEC_OK; + } } else { @@ -2666,11 +2748,12 @@ int main() test_md("234.567","10.555","2.357", 0); test_md("-234.567","10.555","-2.357", 0); test_md("234.567","-10.555","2.357", 0); - if (full) + c.buf[1]=0x3ABECA; + test_md("99999999999999999999999999999999999999","3","0", 0); + if (c.buf[1] != 0x3ABECA) { - c.buf[1]=0x3ABECA; - test_md("99999999999999999999999999999999999999","3","0", 0); - printf("%X\n", c.buf[1]); + printf("%X - overflow\n", c.buf[1]); + exit(1); } printf("==== decimal2bin/bin2decimal ====\n"); @@ -2741,6 +2824,16 @@ int main() test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000", 0); test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000", 0); + b.buf[0]=DIG_BASE+1; + b.buf++; + test_ro(".3", 0, HALF_UP, "0", 0); + b.buf--; + if (b.buf[0] != DIG_BASE+1) + { + printf("%d - underflow\n", b.buf[0]); + exit(1); + } + printf("==== max_decimal ====\n"); test_mx(1,1,"0.9"); test_mx(1,0,"9");