Commit 0ac11a06 authored by bell@51.0.168.192.in-addr.arpa's avatar bell@51.0.168.192.in-addr.arpa

Merge 51.0.168.192.in-addr.arpa:/Users/bell/mysql/bk/mysql-5.0

into 51.0.168.192.in-addr.arpa:/Users/bell/mysql/bk/work-repl-5.0
parents a11369b9 bacdd62f
......@@ -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
......
......@@ -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);
......
......@@ -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;
......@@ -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;
# 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;
......@@ -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
......@@ -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
......
......@@ -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;
}
......
......@@ -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 @@ int TC_LOG_MMAP::recover()
"--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
......
......@@ -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;
......
......@@ -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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment