Merged 5.1 maria with 5.1 maria team tree. Automerge.
This commit is contained in:
commit
56100f3a49
@ -2714,14 +2714,12 @@ if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
|
|||||||
then
|
then
|
||||||
AC_DEFINE([THREAD], [1],
|
AC_DEFINE([THREAD], [1],
|
||||||
[Define if you want to have threaded code. This may be undef on client code])
|
[Define if you want to have threaded code. This may be undef on client code])
|
||||||
# Avoid _PROGRAMS names
|
|
||||||
THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o waiting_threads.o"
|
|
||||||
AC_SUBST(THREAD_LOBJECTS)
|
|
||||||
server_scripts="mysqld_safe mysql_install_db"
|
server_scripts="mysqld_safe mysql_install_db"
|
||||||
sql_server_dirs="strings mysys dbug extra regex"
|
sql_server_dirs="strings mysys dbug extra regex"
|
||||||
|
|
||||||
sql_server="vio sql"
|
sql_server="vio sql"
|
||||||
fi
|
fi
|
||||||
|
AM_CONDITIONAL(THREAD, test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no")
|
||||||
|
|
||||||
# IMPORTANT - do not modify LIBS past this line - this hack is the only way
|
# IMPORTANT - do not modify LIBS past this line - this hack is the only way
|
||||||
# I know to add the static NSS magic if we have static NSS libraries with
|
# I know to add the static NSS magic if we have static NSS libraries with
|
||||||
|
@ -135,7 +135,7 @@ our $default_vardir;
|
|||||||
|
|
||||||
our $opt_usage;
|
our $opt_usage;
|
||||||
our $opt_suites;
|
our $opt_suites;
|
||||||
our $opt_suites_default= "main,binlog,rpl,rpl_ndb,ndb"; # Default suites to run
|
our $opt_suites_default= "main,binlog,rpl,rpl_ndb,ndb,maria"; # Default suites to run
|
||||||
our $opt_script_debug= 0; # Script debugging, enable with --script-debug
|
our $opt_script_debug= 0; # Script debugging, enable with --script-debug
|
||||||
our $opt_verbose= 0; # Verbose output, enable with --verbose
|
our $opt_verbose= 0; # Verbose output, enable with --verbose
|
||||||
|
|
||||||
|
@ -1922,12 +1922,10 @@ check table t2 extended;
|
|||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t2 check status OK
|
test.t2 check status OK
|
||||||
drop table t2;
|
drop table t2;
|
||||||
set session deadlock_timeout_long=60000000;
|
|
||||||
create table t1 (a int unique) transactional=1;
|
create table t1 (a int unique) transactional=1;
|
||||||
insert t1 values (1);
|
insert t1 values (1);
|
||||||
lock table t1 write concurrent;
|
lock table t1 write concurrent;
|
||||||
insert t1 values (2);
|
insert t1 values (2);
|
||||||
set session deadlock_timeout_long=60000000;
|
|
||||||
lock table t1 write concurrent;
|
lock table t1 write concurrent;
|
||||||
insert t1 values (3);
|
insert t1 values (3);
|
||||||
insert t1 values (2);
|
insert t1 values (2);
|
@ -506,7 +506,7 @@ count(*)
|
|||||||
select count(*) from t1 where a >= 4;
|
select count(*) from t1 where a >= 4;
|
||||||
count(*)
|
count(*)
|
||||||
1
|
1
|
||||||
drop table t1;
|
drop table t1, t2;
|
||||||
create table t1 (i int auto_increment not null primary key) transactional=0;
|
create table t1 (i int auto_increment not null primary key) transactional=0;
|
||||||
check table t1 extended;
|
check table t1 extended;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
@ -540,3 +540,14 @@ TABLE_SCHEMA='test' and TABLE_NAME='t1';
|
|||||||
CREATE_OPTIONS
|
CREATE_OPTIONS
|
||||||
transactional=1
|
transactional=1
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 (a int, unique(a)) engine=maria transactional=1;
|
||||||
|
insert into t1 values(1);
|
||||||
|
insert into t1 values(2),(2);
|
||||||
|
ERROR 23000: Duplicate entry '2' for key 'a'
|
||||||
|
create table t2 (a int, unique(a)) engine=maria transactional=0 row_format=dynamic;
|
||||||
|
insert into t2 values(1);
|
||||||
|
insert into t2 values(2),(2);
|
||||||
|
ERROR 23000: Duplicate entry '2' for key 'a'
|
||||||
|
insert into t1 values(3);
|
||||||
|
insert into t2 values(3);
|
||||||
|
drop table t1, t2;
|
@ -1204,13 +1204,11 @@ drop table t2;
|
|||||||
#
|
#
|
||||||
# an example of a deadlock
|
# an example of a deadlock
|
||||||
#
|
#
|
||||||
set session deadlock_timeout_long=60000000;
|
|
||||||
create table t1 (a int unique) transactional=1;
|
create table t1 (a int unique) transactional=1;
|
||||||
insert t1 values (1);
|
insert t1 values (1);
|
||||||
lock table t1 write concurrent;
|
lock table t1 write concurrent;
|
||||||
insert t1 values (2);
|
insert t1 values (2);
|
||||||
connect(con_d,localhost,root,,);
|
connect(con_d,localhost,root,,);
|
||||||
set session deadlock_timeout_long=60000000;
|
|
||||||
lock table t1 write concurrent;
|
lock table t1 write concurrent;
|
||||||
insert t1 values (3);
|
insert t1 values (3);
|
||||||
send insert t1 values (2);
|
send insert t1 values (2);
|
@ -406,7 +406,7 @@ insert into t2 select * from t1;
|
|||||||
insert into t1 select NULL from t2;
|
insert into t1 select NULL from t2;
|
||||||
select count(*) from t1;
|
select count(*) from t1;
|
||||||
select count(*) from t1 where a >= 4;
|
select count(*) from t1 where a >= 4;
|
||||||
drop table t1;
|
drop table t1, t2;
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test problems with small rows and row_type=page
|
# Test problems with small rows and row_type=page
|
||||||
@ -461,6 +461,24 @@ select CREATE_OPTIONS from information_schema.TABLES where
|
|||||||
TABLE_SCHEMA='test' and TABLE_NAME='t1';
|
TABLE_SCHEMA='test' and TABLE_NAME='t1';
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#39697 - Maria: hang when failing to insert due to UNIQUE
|
||||||
|
#
|
||||||
|
create table t1 (a int, unique(a)) engine=maria transactional=1;
|
||||||
|
insert into t1 values(1);
|
||||||
|
--error 1062
|
||||||
|
insert into t1 values(2),(2);
|
||||||
|
create table t2 (a int, unique(a)) engine=maria transactional=0 row_format=dynamic;
|
||||||
|
insert into t2 values(1);
|
||||||
|
--error 1062
|
||||||
|
insert into t2 values(2),(2);
|
||||||
|
connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
|
||||||
|
connection root;
|
||||||
|
insert into t1 values(3);
|
||||||
|
insert into t2 values(3);
|
||||||
|
connection default;
|
||||||
|
drop table t1, t2;
|
||||||
|
|
||||||
# End of 5.1 tests
|
# End of 5.1 tests
|
||||||
|
|
||||||
--disable_result_log
|
--disable_result_log
|
@ -57,11 +57,12 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
|
|||||||
my_memmem.c stacktrace.c \
|
my_memmem.c stacktrace.c \
|
||||||
my_windac.c my_access.c base64.c my_libwrap.c \
|
my_windac.c my_access.c base64.c my_libwrap.c \
|
||||||
wqueue.c
|
wqueue.c
|
||||||
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
|
if THREAD
|
||||||
thr_mutex.c thr_rwlock.c waiting_threads.c \
|
libmysys_a_SOURCES+= thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
|
||||||
CMakeLists.txt mf_soundex.c \
|
thr_mutex.c thr_rwlock.c waiting_threads.c
|
||||||
|
endif
|
||||||
|
EXTRA_DIST = CMakeLists.txt mf_soundex.c \
|
||||||
my_conio.c my_wincond.c my_winthread.c
|
my_conio.c my_wincond.c my_winthread.c
|
||||||
libmysys_a_LIBADD = @THREAD_LOBJECTS@
|
|
||||||
# test_dir_DEPENDENCIES= $(LIBRARIES)
|
# test_dir_DEPENDENCIES= $(LIBRARIES)
|
||||||
# testhash_DEPENDENCIES= $(LIBRARIES)
|
# testhash_DEPENDENCIES= $(LIBRARIES)
|
||||||
# test_charset_DEPENDENCIES= $(LIBRARIES)
|
# test_charset_DEPENDENCIES= $(LIBRARIES)
|
||||||
@ -75,8 +76,6 @@ DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
|
|||||||
-DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
|
-DDEFAULT_SYSCONFDIR="\"$(sysconfdir)\"" \
|
||||||
@DEFS@
|
@DEFS@
|
||||||
|
|
||||||
libmysys_a_DEPENDENCIES= @THREAD_LOBJECTS@
|
|
||||||
|
|
||||||
# I hope this always does the right thing. Otherwise this is only test programs
|
# I hope this always does the right thing. Otherwise this is only test programs
|
||||||
FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @NOINST_LDFLAGS@
|
FLAGS=$(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @NOINST_LDFLAGS@
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ static int match_pins(LF_PINS *el, void *addr)
|
|||||||
#define available_stack_size(CUR,END) (long) ((char*)(END) - (char*)(CUR))
|
#define available_stack_size(CUR,END) (long) ((char*)(END) - (char*)(CUR))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define next_node(P, X) (*((uchar **)(((uchar *)(X)) + (P)->free_ptr_offset)))
|
#define next_node(P, X) (*((uchar * volatile *)(((uchar *)(X)) + (P)->free_ptr_offset)))
|
||||||
#define anext_node(X) next_node(&allocator->pinbox, (X))
|
#define anext_node(X) next_node(&allocator->pinbox, (X))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5727,12 +5727,12 @@ struct my_option my_long_options[] =
|
|||||||
"Short timeout for the two-step deadlock detection (in microseconds)",
|
"Short timeout for the two-step deadlock detection (in microseconds)",
|
||||||
(uchar**) &global_system_variables.wt_timeout_short,
|
(uchar**) &global_system_variables.wt_timeout_short,
|
||||||
(uchar**) &max_system_variables.wt_timeout_short,
|
(uchar**) &max_system_variables.wt_timeout_short,
|
||||||
0, GET_ULONG, REQUIRED_ARG, 100, 0, ULONG_MAX, 0, 0, 0},
|
0, GET_ULONG, REQUIRED_ARG, 10000, 0, ULONG_MAX, 0, 0, 0},
|
||||||
{"deadlock-timeout-long", OPT_DEADLOCK_TIMEOUT_LONG,
|
{"deadlock-timeout-long", OPT_DEADLOCK_TIMEOUT_LONG,
|
||||||
"Long timeout for the two-step deadlock detection (in microseconds)",
|
"Long timeout for the two-step deadlock detection (in microseconds)",
|
||||||
(uchar**) &global_system_variables.wt_timeout_long,
|
(uchar**) &global_system_variables.wt_timeout_long,
|
||||||
(uchar**) &max_system_variables.wt_timeout_long,
|
(uchar**) &max_system_variables.wt_timeout_long,
|
||||||
0, GET_ULONG, REQUIRED_ARG, 10000, 0, ULONG_MAX, 0, 0, 0},
|
0, GET_ULONG, REQUIRED_ARG, 50000000, 0, ULONG_MAX, 0, 0, 0},
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
{"debug", '#', "Debug log.", (uchar**) &default_dbug_option,
|
{"debug", '#', "Debug log.", (uchar**) &default_dbug_option,
|
||||||
(uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
(uchar**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||||
|
@ -2223,7 +2223,8 @@ int ha_maria::extra(enum ha_extra_function operation)
|
|||||||
operation == HA_EXTRA_PREPARE_FOR_RENAME))
|
operation == HA_EXTRA_PREPARE_FOR_RENAME))
|
||||||
{
|
{
|
||||||
THD *thd= table->in_use;
|
THD *thd= table->in_use;
|
||||||
file->trn= THD_TRN;
|
TRN *trn= THD_TRN;
|
||||||
|
_ma_set_trn_for_table(file, trn);
|
||||||
}
|
}
|
||||||
return maria_extra(file, operation, 0);
|
return maria_extra(file, operation, 0);
|
||||||
}
|
}
|
||||||
@ -2296,7 +2297,7 @@ int ha_maria::external_lock(THD *thd, int lock_type)
|
|||||||
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
|
||||||
trans_register_ha(thd, TRUE, maria_hton);
|
trans_register_ha(thd, TRUE, maria_hton);
|
||||||
}
|
}
|
||||||
file->trn= trn;
|
_ma_set_trn_for_table(file, trn);
|
||||||
if (!trnman_increment_locked_tables(trn))
|
if (!trnman_increment_locked_tables(trn))
|
||||||
{
|
{
|
||||||
trans_register_ha(thd, FALSE, maria_hton);
|
trans_register_ha(thd, FALSE, maria_hton);
|
||||||
@ -2352,7 +2353,7 @@ int ha_maria::external_lock(THD *thd, int lock_type)
|
|||||||
if (_ma_reenable_logging_for_table(file, TRUE))
|
if (_ma_reenable_logging_for_table(file, TRUE))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
/** @todo zero file->trn also in commit and rollback */
|
/** @todo zero file->trn also in commit and rollback */
|
||||||
file->trn= 0; // Safety
|
_ma_set_trn_for_table(file, NULL); // Safety
|
||||||
/*
|
/*
|
||||||
Ensure that file->state points to the current number of rows. This
|
Ensure that file->state points to the current number of rows. This
|
||||||
is needed if someone calls maria_info() without first doing an
|
is needed if someone calls maria_info() without first doing an
|
||||||
@ -2409,7 +2410,7 @@ int ha_maria::start_stmt(THD *thd, thr_lock_type lock_type)
|
|||||||
different ha_maria than 'this' then this->file->trn is a stale
|
different ha_maria than 'this' then this->file->trn is a stale
|
||||||
pointer. We fix it:
|
pointer. We fix it:
|
||||||
*/
|
*/
|
||||||
file->trn= trn;
|
_ma_set_trn_for_table(file, trn);
|
||||||
/*
|
/*
|
||||||
As external_lock() was already called, don't increment locked_tables.
|
As external_lock() was already called, don't increment locked_tables.
|
||||||
Note that we call the function below possibly several times when
|
Note that we call the function below possibly several times when
|
||||||
@ -2501,7 +2502,7 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
|
|||||||
MARIA_HA *handler= ((ha_maria*) table->file)->file;
|
MARIA_HA *handler= ((ha_maria*) table->file)->file;
|
||||||
if (handler->s->base.born_transactional)
|
if (handler->s->base.born_transactional)
|
||||||
{
|
{
|
||||||
handler->trn= trn;
|
_ma_set_trn_for_table(handler, trn);
|
||||||
if (handler->s->lock.get_status)
|
if (handler->s->lock.get_status)
|
||||||
{
|
{
|
||||||
if (_ma_setup_live_state(handler))
|
if (_ma_setup_live_state(handler))
|
||||||
|
@ -7081,7 +7081,7 @@ void maria_ignore_trids(MARIA_HA *info)
|
|||||||
if (info->s->base.born_transactional)
|
if (info->s->base.born_transactional)
|
||||||
{
|
{
|
||||||
if (!info->trn)
|
if (!info->trn)
|
||||||
info->trn= &dummy_transaction_object;
|
_ma_set_trn_for_table(info, &dummy_transaction_object);
|
||||||
/* Ignore transaction id when row is read */
|
/* Ignore transaction id when row is read */
|
||||||
info->trn->min_read_from= ~(TrID) 0;
|
info->trn->min_read_from= ~(TrID) 0;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ int maria_begin(MARIA_HA *info)
|
|||||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||||
|
|
||||||
DBUG_PRINT("info", ("TRN set to 0x%lx", (ulong) trn));
|
DBUG_PRINT("info", ("TRN set to 0x%lx", (ulong) trn));
|
||||||
info->trn= trn;
|
_ma_set_trn_for_table(info, trn);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,8 @@ int maria_init(void)
|
|||||||
}
|
}
|
||||||
hash_init(&maria_stored_state, &my_charset_bin, 32,
|
hash_init(&maria_stored_state, &my_charset_bin, 32,
|
||||||
0, sizeof(LSN), 0, (hash_free_key) history_state_free, 0);
|
0, sizeof(LSN), 0, (hash_free_key) history_state_free, 0);
|
||||||
|
DBUG_PRINT("info",("dummy_transaction_object: %p",
|
||||||
|
&dummy_transaction_object));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,8 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
|
|||||||
|
|
||||||
if (!share->base.born_transactional) /* For transactional ones ... */
|
if (!share->base.born_transactional) /* For transactional ones ... */
|
||||||
{
|
{
|
||||||
info.trn= &dummy_transaction_object; /* ... force crash if no trn given */
|
/* ... force crash if no trn given */
|
||||||
|
_ma_set_trn_for_table(&info, &dummy_transaction_object);
|
||||||
info.state= &share->state.state; /* Change global values by default */
|
info.state= &share->state.state; /* Change global values by default */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -194,8 +194,23 @@ int maria_write(MARIA_HA *info, uchar *record)
|
|||||||
Also, filter out non-thread maria use, and table modified in
|
Also, filter out non-thread maria use, and table modified in
|
||||||
the same transaction.
|
the same transaction.
|
||||||
*/
|
*/
|
||||||
if (!local_lock_tree || info->dup_key_trid == info->trn->trid)
|
if (!local_lock_tree)
|
||||||
goto err;
|
goto err;
|
||||||
|
if (info->dup_key_trid == info->trn->trid)
|
||||||
|
{
|
||||||
|
rw_unlock(&keyinfo->root_lock);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* Different TrIDs: table must be transactional */
|
||||||
|
DBUG_ASSERT(share->base.born_transactional);
|
||||||
|
/*
|
||||||
|
If transactions are disabled, and dup_key_trid is different from
|
||||||
|
our TrID, it must be ALTER TABLE with dup_key_trid==0 (no
|
||||||
|
transaction). ALTER TABLE does have MARIA_HA::TRN not dummy but
|
||||||
|
puts TrID=0 in rows/keys.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(share->now_transactional ||
|
||||||
|
(info->dup_key_trid == 0));
|
||||||
blocker= trnman_trid_to_trn(info->trn, info->dup_key_trid);
|
blocker= trnman_trid_to_trn(info->trn, info->dup_key_trid);
|
||||||
/*
|
/*
|
||||||
if blocker TRN was not found, it means that the conflicting
|
if blocker TRN was not found, it means that the conflicting
|
||||||
|
@ -698,6 +698,19 @@ struct st_maria_handler
|
|||||||
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
|
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
|
||||||
#define _ma_have_versioning(info) ((info)->row_flag & ROW_FLAG_TRANSID)
|
#define _ma_have_versioning(info) ((info)->row_flag & ROW_FLAG_TRANSID)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets table's trn and prints debug information
|
||||||
|
@param tbl MARIA_HA of table
|
||||||
|
@param newtrn what to put into tbl->trn
|
||||||
|
@note cast of newtrn is because %p of NULL gives warning (NULL is int)
|
||||||
|
*/
|
||||||
|
#define _ma_set_trn_for_table(tbl, newtrn) do { \
|
||||||
|
DBUG_PRINT("info",("table: %p trn: %p -> %p", \
|
||||||
|
(tbl), (tbl)->trn, (void *)(newtrn))); \
|
||||||
|
(tbl)->trn= (newtrn); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#define MARIA_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
|
#define MARIA_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
|
||||||
/* Don't use to small record-blocks */
|
/* Don't use to small record-blocks */
|
||||||
#define MARIA_EXTEND_BLOCK_LENGTH 20
|
#define MARIA_EXTEND_BLOCK_LENGTH 20
|
||||||
|
@ -54,7 +54,7 @@ pthread_handler_t test_wt(void *arg)
|
|||||||
|
|
||||||
my_rnd_init(&rand, (ulong)(intptr)&m, id);
|
my_rnd_init(&rand, (ulong)(intptr)&m, id);
|
||||||
if (kill_strategy == YOUNGEST)
|
if (kill_strategy == YOUNGEST)
|
||||||
thds[id].thd.weight= ~my_getsystime();
|
thds[id].thd.weight= (ulong volatile)~my_getsystime();
|
||||||
if (kill_strategy == LOCKS)
|
if (kill_strategy == LOCKS)
|
||||||
thds[id].thd.weight= 0;
|
thds[id].thd.weight= 0;
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ retry:
|
|||||||
if (kill_strategy == LOCKS)
|
if (kill_strategy == LOCKS)
|
||||||
thds[id].thd.weight= 0;
|
thds[id].thd.weight= 0;
|
||||||
if (kill_strategy == YOUNGEST)
|
if (kill_strategy == YOUNGEST)
|
||||||
thds[id].thd.weight= ~my_getsystime();
|
thds[id].thd.weight= (ulong volatile)~my_getsystime();
|
||||||
}
|
}
|
||||||
else if (kill_strategy == LOCKS)
|
else if (kill_strategy == LOCKS)
|
||||||
thds[id].thd.weight++;
|
thds[id].thd.weight++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user