Commit e31ffa24 authored by unknown's avatar unknown

making XA tree to compile (and pass tests) in -max build


sql/ha_ndbcluster.cc:
  incorporating changes from Martin
sql/ha_ndbcluster.h:
  incorporating changes from Martin
sql/item_func.h:
  remove a warning
sql/sql_yacc.yy:
  remove a warning
parent 7aa1d93f
...@@ -761,7 +761,7 @@ int ha_archive::rnd_next(byte *buf) ...@@ -761,7 +761,7 @@ int ha_archive::rnd_next(byte *buf)
void ha_archive::position(const byte *record) void ha_archive::position(const byte *record)
{ {
DBUG_ENTER("ha_archive::position"); DBUG_ENTER("ha_archive::position");
ha_store_ptr(ref, ref_length, current_position); my_store_ptr(ref, ref_length, current_position);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -778,7 +778,7 @@ int ha_archive::rnd_pos(byte * buf, byte *pos) ...@@ -778,7 +778,7 @@ int ha_archive::rnd_pos(byte * buf, byte *pos)
DBUG_ENTER("ha_archive::rnd_pos"); DBUG_ENTER("ha_archive::rnd_pos");
statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
&LOCK_status); &LOCK_status);
current_position= ha_get_ptr(pos, ref_length); current_position= my_get_ptr(pos, ref_length);
z_off_t seek= gzseek(archive, current_position, SEEK_SET); z_off_t seek= gzseek(archive, current_position, SEEK_SET);
DBUG_RETURN(get_row(archive, buf)); DBUG_RETURN(get_row(archive, buf));
......
...@@ -106,6 +106,6 @@ public: ...@@ -106,6 +106,6 @@ public:
enum thr_lock_type lock_type); enum thr_lock_type lock_type);
}; };
bool archive_db_init(void); handlerton *archive_db_init(void);
bool archive_db_end(void); bool archive_db_end(void);
...@@ -45,6 +45,23 @@ static const int max_transactions= 256; ...@@ -45,6 +45,23 @@ static const int max_transactions= 256;
static const char *ha_ndb_ext=".ndb"; static const char *ha_ndb_ext=".ndb";
static int ndbcluster_close_connection(THD *thd);
static int ndbcluster_commit(THD *thd, bool all);
static int ndbcluster_rollback(THD *thd, bool all);
static handlerton ndbcluster_hton = {
0, /* slot */
0, /* savepoint size */
ndbcluster_close_connection,
NULL, /* savepoint_set */
NULL, /* savepoint_rollback */
NULL, /* savepoint_release */
ndbcluster_commit,
ndbcluster_rollback,
NULL, /* prepare */
NULL /* recover */
};
#define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8 #define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8
...@@ -258,6 +275,8 @@ Thd_ndb::Thd_ndb() ...@@ -258,6 +275,8 @@ Thd_ndb::Thd_ndb()
ndb= new Ndb(g_ndb_cluster_connection, ""); ndb= new Ndb(g_ndb_cluster_connection, "");
lock_count= 0; lock_count= 0;
count= 0; count= 0;
all= NULL;
stmt= NULL;
error= 0; error= 0;
} }
...@@ -268,10 +287,18 @@ Thd_ndb::~Thd_ndb() ...@@ -268,10 +287,18 @@ Thd_ndb::~Thd_ndb()
ndb= 0; ndb= 0;
} }
inline
Thd_ndb *
get_thd_ndb(THD *thd) { return (Thd_ndb *) thd->ha_data[ndbcluster_hton.slot]; }
inline
void
set_thd_ndb(THD *thd, Thd_ndb *thd_ndb) { thd->ha_data[ndbcluster_hton.slot]= thd_ndb; }
inline inline
Ndb *ha_ndbcluster::get_ndb() Ndb *ha_ndbcluster::get_ndb()
{ {
return ((Thd_ndb*)current_thd->transaction.thd_ndb)->ndb; return get_thd_ndb(table->in_use)->ndb;
} }
/* /*
...@@ -315,7 +342,7 @@ void ha_ndbcluster::records_update() ...@@ -315,7 +342,7 @@ void ha_ndbcluster::records_update()
} }
{ {
THD *thd= current_thd; THD *thd= current_thd;
if (((Thd_ndb*)(thd->transaction.thd_ndb))->error) if (get_thd_ndb(thd)->error)
info->no_uncommitted_rows_count= 0; info->no_uncommitted_rows_count= 0;
} }
records= info->records+ info->no_uncommitted_rows_count; records= info->records+ info->no_uncommitted_rows_count;
...@@ -327,8 +354,7 @@ void ha_ndbcluster::no_uncommitted_rows_execute_failure() ...@@ -327,8 +354,7 @@ void ha_ndbcluster::no_uncommitted_rows_execute_failure()
if (m_ha_not_exact_count) if (m_ha_not_exact_count)
return; return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_execute_failure"); DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_execute_failure");
THD *thd= current_thd; get_thd_ndb(table->in_use)->error= 1;
((Thd_ndb*)(thd->transaction.thd_ndb))->error= 1;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -338,7 +364,7 @@ void ha_ndbcluster::no_uncommitted_rows_init(THD *thd) ...@@ -338,7 +364,7 @@ void ha_ndbcluster::no_uncommitted_rows_init(THD *thd)
return; return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_init"); DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_init");
struct Ndb_table_local_info *info= (struct Ndb_table_local_info *)m_table_info; struct Ndb_table_local_info *info= (struct Ndb_table_local_info *)m_table_info;
Thd_ndb *thd_ndb= (Thd_ndb *)thd->transaction.thd_ndb; Thd_ndb *thd_ndb= get_thd_ndb(thd);
if (info->last_count != thd_ndb->count) if (info->last_count != thd_ndb->count)
{ {
info->last_count= thd_ndb->count; info->last_count= thd_ndb->count;
...@@ -370,8 +396,9 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd) ...@@ -370,8 +396,9 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd)
if (m_ha_not_exact_count) if (m_ha_not_exact_count)
return; return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_reset"); DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_reset");
((Thd_ndb*)(thd->transaction.thd_ndb))->count++; Thd_ndb *thd_ndb= get_thd_ndb(thd);
((Thd_ndb*)(thd->transaction.thd_ndb))->error= 0; thd_ndb->count++;
thd_ndb->error= 0;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -3136,9 +3163,9 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd, ...@@ -3136,9 +3163,9 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd,
As MySQL will execute an external lock for every new table it uses As MySQL will execute an external lock for every new table it uses
we can use this to start the transactions. we can use this to start the transactions.
If we are in auto_commit mode we just need to start a transaction If we are in auto_commit mode we just need to start a transaction
for the statement, this will be stored in transaction.stmt. for the statement, this will be stored in thd_ndb.stmt.
If not, we have to start a master transaction if there doesn't exist If not, we have to start a master transaction if there doesn't exist
one from before, this will be stored in transaction.all one from before, this will be stored in thd_ndb.all
When a table lock is held one transaction will be started which holds When a table lock is held one transaction will be started which holds
the table lock and for each statement a hupp transaction will be started the table lock and for each statement a hupp transaction will be started
...@@ -3157,7 +3184,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ...@@ -3157,7 +3184,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
if (check_ndb_connection()) if (check_ndb_connection())
DBUG_RETURN(1); DBUG_RETURN(1);
Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb; Thd_ndb *thd_ndb= get_thd_ndb(thd);
Ndb *ndb= thd_ndb->ndb; Ndb *ndb= thd_ndb->ndb;
DBUG_PRINT("enter", ("transaction.thd_ndb->lock_count: %d", DBUG_PRINT("enter", ("transaction.thd_ndb->lock_count: %d",
...@@ -3173,18 +3200,19 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ...@@ -3173,18 +3200,19 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK))) if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | OPTION_TABLE_LOCK)))
{ {
// Autocommit transaction // Autocommit transaction
DBUG_ASSERT(!thd->transaction.stmt.ndb_tid); DBUG_ASSERT(!thd_ndb->stmt);
DBUG_PRINT("trans",("Starting transaction stmt")); DBUG_PRINT("trans",("Starting transaction stmt"));
trans= ndb->startTransaction(); trans= ndb->startTransaction();
if (trans == NULL) if (trans == NULL)
ERR_RETURN(ndb->getNdbError()); ERR_RETURN(ndb->getNdbError());
no_uncommitted_rows_reset(thd); no_uncommitted_rows_reset(thd);
thd->transaction.stmt.ndb_tid= trans; thd_ndb->stmt= trans;
trans_register_ha(thd, FALSE, &ndbcluster_hton);
} }
else else
{ {
if (!thd->transaction.all.ndb_tid) if (!thd_ndb->all)
{ {
// Not autocommit transaction // Not autocommit transaction
// A "master" transaction ha not been started yet // A "master" transaction ha not been started yet
...@@ -3194,6 +3222,8 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ...@@ -3194,6 +3222,8 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
if (trans == NULL) if (trans == NULL)
ERR_RETURN(ndb->getNdbError()); ERR_RETURN(ndb->getNdbError());
no_uncommitted_rows_reset(thd); no_uncommitted_rows_reset(thd);
thd_ndb->all= trans;
trans_register_ha(thd, TRUE, &ndbcluster_hton);
/* /*
If this is the start of a LOCK TABLE, a table look If this is the start of a LOCK TABLE, a table look
...@@ -3207,7 +3237,6 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ...@@ -3207,7 +3237,6 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
DBUG_PRINT("info", ("Locking the table..." )); DBUG_PRINT("info", ("Locking the table..." ));
} }
thd->transaction.all.ndb_tid= trans;
} }
} }
} }
...@@ -3232,9 +3261,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ...@@ -3232,9 +3261,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
else else
m_transaction_on= thd->variables.ndb_use_transactions; m_transaction_on= thd->variables.ndb_use_transactions;
m_active_trans= thd->transaction.all.ndb_tid ? m_active_trans= thd_ndb->all ? thd_ndb->all : thd_ndb->stmt;
(NdbTransaction*)thd->transaction.all.ndb_tid:
(NdbTransaction*)thd->transaction.stmt.ndb_tid;
DBUG_ASSERT(m_active_trans); DBUG_ASSERT(m_active_trans);
// Start of transaction // Start of transaction
m_retrieve_all_fields= FALSE; m_retrieve_all_fields= FALSE;
...@@ -3260,7 +3287,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ...@@ -3260,7 +3287,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
DBUG_PRINT("trans", ("Last external_lock")); DBUG_PRINT("trans", ("Last external_lock"));
PRINT_OPTION_FLAGS(thd); PRINT_OPTION_FLAGS(thd);
if (thd->transaction.stmt.ndb_tid) if (thd_ndb->stmt)
{ {
/* /*
Unlock is done without a transaction commit / rollback. Unlock is done without a transaction commit / rollback.
...@@ -3269,7 +3296,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) ...@@ -3269,7 +3296,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
*/ */
DBUG_PRINT("trans",("ending non-updating transaction")); DBUG_PRINT("trans",("ending non-updating transaction"));
ndb->closeTransaction(m_active_trans); ndb->closeTransaction(m_active_trans);
thd->transaction.stmt.ndb_tid= 0; thd_ndb->stmt= NULL;
} }
} }
m_table= NULL; m_table= NULL;
...@@ -3316,14 +3343,14 @@ int ha_ndbcluster::start_stmt(THD *thd) ...@@ -3316,14 +3343,14 @@ int ha_ndbcluster::start_stmt(THD *thd)
DBUG_ENTER("start_stmt"); DBUG_ENTER("start_stmt");
PRINT_OPTION_FLAGS(thd); PRINT_OPTION_FLAGS(thd);
NdbTransaction *trans= (NdbTransaction*)thd->transaction.stmt.ndb_tid; Thd_ndb *thd_ndb= get_thd_ndb(thd);
NdbTransaction *trans= thd_ndb->stmt;
if (!trans){ if (!trans){
Ndb *ndb= ((Thd_ndb*)thd->transaction.thd_ndb)->ndb; Ndb *ndb= thd_ndb->ndb;
DBUG_PRINT("trans",("Starting transaction stmt")); DBUG_PRINT("trans",("Starting transaction stmt"));
#if 0 #if 0
NdbTransaction *tablock_trans= NdbTransaction *tablock_trans= thd_ndb->all;
(NdbTransaction*)thd->transaction.all.ndb_tid;
DBUG_PRINT("info", ("tablock_trans: %x", (UintPtr)tablock_trans)); DBUG_PRINT("info", ("tablock_trans: %x", (UintPtr)tablock_trans));
DBUG_ASSERT(tablock_trans); DBUG_ASSERT(tablock_trans);
// trans= ndb->hupp(tablock_trans); // trans= ndb->hupp(tablock_trans);
...@@ -3332,7 +3359,8 @@ int ha_ndbcluster::start_stmt(THD *thd) ...@@ -3332,7 +3359,8 @@ int ha_ndbcluster::start_stmt(THD *thd)
if (trans == NULL) if (trans == NULL)
ERR_RETURN(ndb->getNdbError()); ERR_RETURN(ndb->getNdbError());
no_uncommitted_rows_reset(thd); no_uncommitted_rows_reset(thd);
thd->transaction.stmt.ndb_tid= trans; thd_ndb->stmt= trans;
trans_register_ha(thd, FALSE, &ndbcluster_hton);
} }
m_active_trans= trans; m_active_trans= trans;
...@@ -3349,15 +3377,16 @@ int ha_ndbcluster::start_stmt(THD *thd) ...@@ -3349,15 +3377,16 @@ int ha_ndbcluster::start_stmt(THD *thd)
Commit a transaction started in NDB Commit a transaction started in NDB
*/ */
int ndbcluster_commit(THD *thd, void *ndb_transaction) int ndbcluster_commit(THD *thd, bool all)
{ {
int res= 0; int res= 0;
Ndb *ndb= ((Thd_ndb*)thd->transaction.thd_ndb)->ndb; Thd_ndb *thd_ndb= get_thd_ndb(thd);
NdbTransaction *trans= (NdbTransaction*)ndb_transaction; Ndb *ndb= thd_ndb->ndb;
NdbTransaction *trans= all ? thd_ndb->all : thd_ndb->stmt;
DBUG_ENTER("ndbcluster_commit"); DBUG_ENTER("ndbcluster_commit");
DBUG_PRINT("transaction",("%s", DBUG_PRINT("transaction",("%s",
trans == thd->transaction.stmt.ndb_tid ? trans == thd_ndb->stmt ?
"stmt" : "all")); "stmt" : "all"));
DBUG_ASSERT(ndb && trans); DBUG_ASSERT(ndb && trans);
...@@ -3371,6 +3400,7 @@ int ndbcluster_commit(THD *thd, void *ndb_transaction) ...@@ -3371,6 +3400,7 @@ int ndbcluster_commit(THD *thd, void *ndb_transaction)
ndbcluster_print_error(res, error_op); ndbcluster_print_error(res, error_op);
} }
ndb->closeTransaction(trans); ndb->closeTransaction(trans);
thd_ndb->all= thd_ndb->stmt= NULL;
DBUG_RETURN(res); DBUG_RETURN(res);
} }
...@@ -3379,15 +3409,16 @@ int ndbcluster_commit(THD *thd, void *ndb_transaction) ...@@ -3379,15 +3409,16 @@ int ndbcluster_commit(THD *thd, void *ndb_transaction)
Rollback a transaction started in NDB Rollback a transaction started in NDB
*/ */
int ndbcluster_rollback(THD *thd, void *ndb_transaction) int ndbcluster_rollback(THD *thd, bool all)
{ {
int res= 0; int res= 0;
Ndb *ndb= ((Thd_ndb*)thd->transaction.thd_ndb)->ndb; Thd_ndb *thd_ndb= get_thd_ndb(thd);
NdbTransaction *trans= (NdbTransaction*)ndb_transaction; Ndb *ndb= thd_ndb->ndb;
NdbTransaction *trans= all ? thd_ndb->all : thd_ndb->stmt;
DBUG_ENTER("ndbcluster_rollback"); DBUG_ENTER("ndbcluster_rollback");
DBUG_PRINT("transaction",("%s", DBUG_PRINT("transaction",("%s",
trans == thd->transaction.stmt.ndb_tid ? trans == thd_ndb->stmt ?
"stmt" : "all")); "stmt" : "all"));
DBUG_ASSERT(ndb && trans); DBUG_ASSERT(ndb && trans);
...@@ -3401,7 +3432,8 @@ int ndbcluster_rollback(THD *thd, void *ndb_transaction) ...@@ -3401,7 +3432,8 @@ int ndbcluster_rollback(THD *thd, void *ndb_transaction)
ndbcluster_print_error(res, error_op); ndbcluster_print_error(res, error_op);
} }
ndb->closeTransaction(trans); ndb->closeTransaction(trans);
DBUG_RETURN(0); thd_ndb->all= thd_ndb->stmt= NULL;
DBUG_RETURN(res);
} }
...@@ -4257,12 +4289,12 @@ void ha_ndbcluster::release_thd_ndb(Thd_ndb* thd_ndb) ...@@ -4257,12 +4289,12 @@ void ha_ndbcluster::release_thd_ndb(Thd_ndb* thd_ndb)
Ndb* check_ndb_in_thd(THD* thd) Ndb* check_ndb_in_thd(THD* thd)
{ {
Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb; Thd_ndb *thd_ndb= get_thd_ndb(thd);
if (!thd_ndb) if (!thd_ndb)
{ {
if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb())) if (!(thd_ndb= ha_ndbcluster::seize_thd_ndb()))
return NULL; return NULL;
thd->transaction.thd_ndb= thd_ndb; set_thd_ndb(thd, thd_ndb);
} }
return thd_ndb->ndb; return thd_ndb->ndb;
} }
...@@ -4282,16 +4314,16 @@ int ha_ndbcluster::check_ndb_connection() ...@@ -4282,16 +4314,16 @@ int ha_ndbcluster::check_ndb_connection()
} }
void ndbcluster_close_connection(THD *thd) int ndbcluster_close_connection(THD *thd)
{ {
Thd_ndb *thd_ndb= (Thd_ndb*)thd->transaction.thd_ndb; Thd_ndb *thd_ndb= get_thd_ndb(thd);
DBUG_ENTER("ndbcluster_close_connection"); DBUG_ENTER("ndbcluster_close_connection");
if (thd_ndb) if (thd_ndb)
{ {
ha_ndbcluster::release_thd_ndb(thd_ndb); ha_ndbcluster::release_thd_ndb(thd_ndb);
thd->transaction.thd_ndb= NULL; set_thd_ndb(thd, NULL); // not strictly required but does not hurt either
} }
DBUG_VOID_RETURN; DBUG_RETURN(0);
} }
...@@ -4554,7 +4586,8 @@ static int connect_callback() ...@@ -4554,7 +4586,8 @@ static int connect_callback()
return 0; return 0;
} }
bool ndbcluster_init() handlerton *
ndbcluster_init()
{ {
int res; int res;
DBUG_ENTER("ndbcluster_init"); DBUG_ENTER("ndbcluster_init");
...@@ -4630,11 +4663,11 @@ bool ndbcluster_init() ...@@ -4630,11 +4663,11 @@ bool ndbcluster_init()
} }
ndbcluster_inited= 1; ndbcluster_inited= 1;
DBUG_RETURN(FALSE); DBUG_RETURN(&ndbcluster_hton);
ndbcluster_init_error: ndbcluster_init_error:
ndbcluster_end(); ndbcluster_end();
DBUG_RETURN(TRUE); DBUG_RETURN(NULL);
} }
......
...@@ -74,6 +74,8 @@ class Thd_ndb { ...@@ -74,6 +74,8 @@ class Thd_ndb {
Ndb *ndb; Ndb *ndb;
ulong count; ulong count;
uint lock_count; uint lock_count;
NdbTransaction *all;
NdbTransaction *stmt;
int error; int error;
}; };
...@@ -286,14 +288,9 @@ private: ...@@ -286,14 +288,9 @@ private:
extern struct show_var_st ndb_status_variables[]; extern struct show_var_st ndb_status_variables[];
bool ndbcluster_init(void); handlerton *ndbcluster_init(void);
bool ndbcluster_end(void); bool ndbcluster_end(void);
int ndbcluster_commit(THD *thd, void* ndb_transaction);
int ndbcluster_rollback(THD *thd, void* ndb_transaction);
void ndbcluster_close_connection(THD *thd);
int ndbcluster_discover(THD* thd, const char* dbname, const char* name, int ndbcluster_discover(THD* thd, const char* dbname, const char* name,
const void** frmblob, uint* frmlen); const void** frmblob, uint* frmlen);
int ndbcluster_find_files(THD *thd,const char *db,const char *path, int ndbcluster_find_files(THD *thd,const char *db,const char *path,
......
...@@ -348,7 +348,7 @@ class Item_func_div :public Item_num_op ...@@ -348,7 +348,7 @@ class Item_func_div :public Item_num_op
{ {
public: public:
Item_func_div(Item *a,Item *b) :Item_num_op(a,b) {} Item_func_div(Item *a,Item *b) :Item_num_op(a,b) {}
longlong int_op() { DBUG_ASSERT(0); } longlong int_op() { DBUG_ASSERT(0); return 0; }
double real_op(); double real_op();
my_decimal *decimal_op(my_decimal *); my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "/"; } const char *func_name() const { return "/"; }
......
...@@ -1924,7 +1924,7 @@ sp_proc_stmt: ...@@ -1924,7 +1924,7 @@ sp_proc_stmt:
sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(), sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(),
lex->spcont, lex->spcont,
offset, $2, MYSQL_TYPE_STRING); offset, $2, MYSQL_TYPE_STRING);
LEX_STRING dummy={"", 0}; LEX_STRING dummy={(char*)"", 0};
lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in); lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in);
i->tables= lex->query_tables; i->tables= lex->query_tables;
......
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