diff options
-rw-r--r-- | .bzrignore | 21 | ||||
-rw-r--r-- | myisam/mi_dynrec.c | 68 | ||||
-rw-r--r-- | mysql-test/r/almost_full.result | 29 | ||||
-rw-r--r-- | mysql-test/t/almost_full.test | 41 |
4 files changed, 149 insertions, 10 deletions
diff --git a/.bzrignore b/.bzrignore index 35f5199be3c..9b90cd97d84 100644 --- a/.bzrignore +++ b/.bzrignore @@ -4,8 +4,6 @@ *.bb *.bbg *.bin -*.vcproj.cmake -cmake_install.cmake *.cdf *.core *.d @@ -33,6 +31,7 @@ cmake_install.cmake *.spec *.user *.vcproj +*.vcproj.cmake */*.dir/* */*_pure_*warnings */.deps @@ -347,6 +346,7 @@ client/tmp.diff client_debug/* client_release/* client_test +cmake_install.cmake cmd-line-utils/libedit/common.h cmd-line-utils/libedit/makelist comon.h @@ -366,6 +366,9 @@ contrib/*.vcproj core core.* core.2430 +cscope.in.out +cscope.out +cscope.po.out db-*.*.* dbug/*.ds? dbug/*.vcproj @@ -377,6 +380,8 @@ dbug/main.r dbug/output*.r dbug/user.ps dbug/user.t +debian/control +debian/defs.mk depcomp emacs.h examples/*.ds? @@ -413,6 +418,7 @@ heap/hp_test2 help help.c help.h +include/abi_check include/check_abi include/my_config.h include/my_global.h @@ -472,6 +478,7 @@ libmysql/release/libmysql.exp libmysql/vio_priv.h libmysql_r/*.c libmysql_r/acconfig.h +libmysql_r/client_settings.h libmysql_r/conf_to_src libmysql_r/my_static.h libmysql_r/mysys_priv.h @@ -1257,6 +1264,7 @@ support-files/mysql-3.23.29-gamma.spec support-files/mysql-log-rotate support-files/mysql.server support-files/mysql.spec +support-files/mysqld_multi.server support-files/ndb-config-2-node.ini tags test/ndbapi/bank/bankCreator @@ -1315,6 +1323,7 @@ test_xml tests/*.ds? tests/*.vcproj tests/.libs -prune +tests/bug25714 tests/client_test tests/connect_test tests/mysql_client_test @@ -1342,11 +1351,3 @@ win/vs71cache.txt win/vs8cache.txt zlib/*.ds? zlib/*.vcproj -debian/control -debian/defs.mk -include/abi_check -support-files/mysqld_multi.server -tests/bug25714 -cscope.in.out -cscope.out -cscope.po.out diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 11f51f08d23..67d40ec50bf 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -144,6 +144,29 @@ static int write_dynamic_record(MI_INFO *info, const byte *record, DBUG_ENTER("write_dynamic_record"); flag=0; + + /* + Check if we have enough room for the new record. + First we do simplified check to make usual case faster. + Then we do more precise check for the space left. + Though it still is not absolutely precise, as + we always use MI_MAX_DYN_BLOCK_HEADER while it can be + less in the most of the cases. + */ + + if (unlikely(info->s->base.max_data_file_length - + info->state->data_file_length < + reclength + MI_MAX_DYN_BLOCK_HEADER)) + { + if (info->s->base.max_data_file_length - info->state->data_file_length + + info->state->empty - info->state->del * MI_MAX_DYN_BLOCK_HEADER < + reclength + MI_MAX_DYN_BLOCK_HEADER) + { + my_errno=HA_ERR_RECORD_FILE_FULL; + DBUG_RETURN(1); + } + } + do { if (_mi_find_writepos(info,reclength,&filepos,&length)) @@ -580,6 +603,51 @@ static int update_dynamic_record(MI_INFO *info, my_off_t filepos, byte *record, DBUG_ENTER("update_dynamic_record"); flag=block_info.second_read=0; + /* + Check if we have enough room for the record. + First we do simplified check to make usual case faster. + Then we do more precise check for the space left. + Though it still is not absolutely precise, as + we always use MI_MAX_DYN_BLOCK_HEADER while it can be + less in the most of the cases. + */ + + /* + compare with just the reclength as we're going + to get some space from the old replaced record + */ + if (unlikely(info->s->base.max_data_file_length - + info->state->data_file_length < reclength)) + { + /* + let's read the old record's block to find out the length of the + old record + */ + if ((error=_mi_get_block_info(&block_info,info->dfile,filepos)) + & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR | BLOCK_FATAL_ERROR)) + { + DBUG_PRINT("error",("Got wrong block info")); + if (!(error & BLOCK_FATAL_ERROR)) + my_errno=HA_ERR_WRONG_IN_RECORD; + goto err; + } + + /* + if new record isn't longer, we can go on safely + */ + if (block_info.rec_len < reclength) + { + if (info->s->base.max_data_file_length - info->state->data_file_length + + info->state->empty - info->state->del * MI_MAX_DYN_BLOCK_HEADER < + reclength - block_info.rec_len + MI_MAX_DYN_BLOCK_HEADER) + { + my_errno=HA_ERR_RECORD_FILE_FULL; + goto err; + } + } + block_info.second_read=0; + } + while (reclength > 0) { if (filepos != info->s->state.dellink) diff --git a/mysql-test/r/almost_full.result b/mysql-test/r/almost_full.result new file mode 100644 index 00000000000..eb28f12fa51 --- /dev/null +++ b/mysql-test/r/almost_full.result @@ -0,0 +1,29 @@ +drop table if exists t1; +set global myisam_data_pointer_size=2; +CREATE TABLE t1 (a int auto_increment primary key not null, b longtext) ENGINE=MyISAM; +DELETE FROM t1 WHERE a=1 or a=5; +INSERT INTO t1 SET b=repeat('a',600); +ERROR HY000: The table 't1' is full +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check warning Datafile is almost full, 65448 of 65534 used +test.t1 check status OK +UPDATE t1 SET b=repeat('a', 800) where a=10; +ERROR HY000: The table 't1' is full +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check warning Datafile is almost full, 65448 of 65534 used +test.t1 check status OK +INSERT INTO t1 SET b=repeat('a',400); +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check warning Datafile is almost full, 65448 of 65534 used +test.t1 check status OK +DELETE FROM t1 WHERE a=2 or a=6; +UPDATE t1 SET b=repeat('a', 600) where a=11; +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check warning Datafile is almost full, 65448 of 65534 used +test.t1 check status OK +drop table t1; +set global myisam_data_pointer_size=default; diff --git a/mysql-test/t/almost_full.test b/mysql-test/t/almost_full.test new file mode 100644 index 00000000000..5c67ab3c088 --- /dev/null +++ b/mysql-test/t/almost_full.test @@ -0,0 +1,41 @@ +# +# Some special cases with empty tables +# + +--disable_warnings +drop table if exists t1; +--enable_warnings + +set global myisam_data_pointer_size=2; +CREATE TABLE t1 (a int auto_increment primary key not null, b longtext) ENGINE=MyISAM; + +--disable_query_log +let $1= 303; +while ($1) +{ + INSERT INTO t1 SET b=repeat('a',200); + dec $1; +} +--enable_query_log + +DELETE FROM t1 WHERE a=1 or a=5; + +--error 1114 +INSERT INTO t1 SET b=repeat('a',600); +CHECK TABLE t1 EXTENDED; + +--error 1114 +UPDATE t1 SET b=repeat('a', 800) where a=10; +CHECK TABLE t1 EXTENDED; + +INSERT INTO t1 SET b=repeat('a',400); +CHECK TABLE t1 EXTENDED; + +DELETE FROM t1 WHERE a=2 or a=6; +UPDATE t1 SET b=repeat('a', 600) where a=11; +CHECK TABLE t1 EXTENDED; +drop table t1; + +set global myisam_data_pointer_size=default; + +# End of 4.1 tests |