Skip to content
32 changes: 32 additions & 0 deletions mysql-test/main/backup_server_block.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
connect con1,localhost,root,,test;
connect con2,localhost,root,,test;
connection con1;
SET DEBUG_SYNC='after_backup_server_lock_acquired SIGNAL in_progress WAIT_FOR finish';
BACKUP SERVER TO '<MYSQLTEST_VARDIR>/some_directory';
connection default;
SET DEBUG_SYNC='now WAIT_FOR in_progress';
connection con2;
BACKUP SERVER TO '<MYSQLTEST_VARDIR>/other_directory';
connection default;
SET @con2_id = <con2_id>;
SELECT COMMAND, STATE, INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = @con2_id;
COMMAND STATE INFO
Query Waiting for backup lock BACKUP SERVER TO '<MYSQLTEST_VARDIR>/other_directory'
SET DEBUG_SYNC='now SIGNAL finish';
connection con1;
connection default;
connection con2;
connection default;
SET DEBUG_SYNC='RESET';
BACKUP STAGE START;
connection con2;
BACKUP SERVER TO '<MYSQLTEST_VARDIR>/another_directory';
connection default;
SELECT COMMAND, STATE, INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = @con2_id;
COMMAND STATE INFO
Query Waiting for backup lock BACKUP SERVER TO '<MYSQLTEST_VARDIR>/another_directory'
BACKUP STAGE END;
connection con2;
connection default;
disconnect con1;
disconnect con2;
86 changes: 86 additions & 0 deletions mysql-test/main/backup_server_block.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Check that BACKUP SERVER blocks when another BACKUP SERVER is in progress

--source include/have_debug_sync.inc

--connect (con1,localhost,root,,test)
--connect (con2,localhost,root,,test)

--connection con1
# Simulate long-running backup by blocking it on a debug sync point
SET DEBUG_SYNC='after_backup_server_lock_acquired SIGNAL in_progress WAIT_FOR finish';
--replace_result $MYSQLTEST_VARDIR <MYSQLTEST_VARDIR>
--send_eval BACKUP SERVER TO '$MYSQLTEST_VARDIR/some_directory'

--connection default
# Wait for the "long-running" backup to lock the system
SET DEBUG_SYNC='now WAIT_FOR in_progress';

--connection con2
let $con2_id= `SELECT CONNECTION_ID()`;
# Attempt a backup while the other backup is running
--replace_result $MYSQLTEST_VARDIR <MYSQLTEST_VARDIR>
--send_eval BACKUP SERVER TO '$MYSQLTEST_VARDIR/other_directory'

--connection default
# Check that the backup on con2 is waiting for the backup on con1
--replace_result $con2_id <con2_id>
eval SET @con2_id = $con2_id;
let $wait_condition=
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE ID = @con2_id AND State = 'Waiting for backup lock';
--source include/wait_condition.inc
--replace_result $MYSQLTEST_VARDIR <MYSQLTEST_VARDIR>
SELECT COMMAND, STATE, INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = @con2_id;

SET DEBUG_SYNC='now SIGNAL finish';

--connection con1
--reap

--connection default
# When "long running" backup finishes, check that the backup on con2
# is also allowed to finish
let $wait_condition=
SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE Info LIKE 'BACKUP SERVER TO %' AND State = 'Waiting for backup lock';
--source include/wait_condition.inc

--connection con2
--reap

--connection default
SET DEBUG_SYNC='RESET';

# Test that BACKUP SERVER blocks when a BACKUP STAGE process is in progress

BACKUP STAGE START;

--connection con2
--replace_result $MYSQLTEST_VARDIR <MYSQLTEST_VARDIR>
--send_eval BACKUP SERVER TO '$MYSQLTEST_VARDIR/another_directory'

--connection default
let $wait_condition=
SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE ID = @con2_id AND State = 'Waiting for backup lock';
--source include/wait_condition.inc
--replace_result $MYSQLTEST_VARDIR <MYSQLTEST_VARDIR>
SELECT COMMAND, STATE, INFO FROM INFORMATION_SCHEMA.PROCESSLIST WHERE ID = @con2_id;

BACKUP STAGE END;

# When "long running" backup finishes, check that the backup on con2
# is also allowed to finish
let $wait_condition=
SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.PROCESSLIST
WHERE Info LIKE 'BACKUP SERVER TO %' AND State = 'Waiting for backup lock';
--source include/wait_condition.inc

--connection con2
--reap

--connection default

--disconnect con1
--disconnect con2

2 changes: 2 additions & 0 deletions sql/debug_sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
Declarations for the Debug Sync Facility. See debug_sync.cc for details.
*/

#include <my_global.h>

class THD;

#if defined(ENABLED_DEBUG_SYNC)
Expand Down
14 changes: 7 additions & 7 deletions sql/mdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ class MDL_request
/** Set type of lock request. Can be only applied to pending locks. */
inline void set_type(enum_mdl_type type_arg)
{
DBUG_ASSERT(ticket == NULL);
DBUG_ASSERT(ticket == nullptr);
type= type_arg;
}
void move_from(MDL_request &from)
Expand All @@ -589,7 +589,7 @@ class MDL_request
next_in_list= from.next_in_list;
prev_in_list= from.prev_in_list;
key.mdl_key_init(&from.key);
from.ticket= NULL; // that's what "move" means
from.ticket= nullptr; // that's what "move" means
}

/**
Expand Down Expand Up @@ -621,17 +621,17 @@ class MDL_request
MDL_request& operator=(const MDL_request &)
{
type= MDL_NOT_INITIALIZED;
ticket= NULL;
ticket= nullptr;
/* Do nothing, in particular, don't try to copy the key. */
return *this;
}
/* Another piece of ugliness for TABLE_LIST constructor */
MDL_request(): type(MDL_NOT_INITIALIZED), ticket(NULL) {}
MDL_request(): type(MDL_NOT_INITIALIZED), ticket(nullptr) {}

MDL_request(const MDL_request *rhs)
:type(rhs->type),
duration(rhs->duration),
ticket(NULL),
ticket(nullptr),
key(&rhs->key)
{}
};
Expand Down Expand Up @@ -1088,7 +1088,7 @@ class MDL_context
void done_waiting_for()
{
mysql_prlock_wrlock(&m_LOCK_waiting_for);
m_waiting_for= NULL;
m_waiting_for= nullptr;
mysql_prlock_unlock(&m_LOCK_waiting_for);
}
void lock_deadlock_victim()
Expand Down Expand Up @@ -1116,7 +1116,7 @@ class MDL_context
The coordinator thread holds the lock for the duration of worker's purge
job, or longer, possibly reusing shared MDL for different workers and jobs.
*/
MDL_context *lock_warrant= NULL;
MDL_context *lock_warrant= nullptr;

inline bool is_lock_warrantee(MDL_key::enum_mdl_namespace ns,
const char *db, const char *name,
Expand Down
10 changes: 6 additions & 4 deletions sql/sql_plist.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */


#include <my_global.h>

template <typename T, typename L>
class I_P_List_iterator;
class I_P_List_null_counter;
Expand Down Expand Up @@ -72,14 +74,14 @@ class I_P_List : public C, public I
is a bad idea.
*/
public:
I_P_List() : I(&m_first), m_first(NULL) {};
I_P_List() : I(&m_first), m_first(nullptr) {};
/*
empty() is used in many places in the code instead of a constructor, to
initialize a bzero-ed I_P_List instance.
*/

inline void empty() { m_first= NULL; C::reset(); I::set_last(&m_first); }
inline bool is_empty() const { return (m_first == NULL); }
inline void empty() { m_first= nullptr; C::reset(); I::set_last(&m_first); }
inline bool is_empty() const { return (m_first == nullptr); }
inline void push_front(T* a)
{
*B::next_ptr(a)= m_first;
Expand All @@ -102,7 +104,7 @@ class I_P_List : public C, public I
}
inline void insert_after(T *pos, T *a)
{
if (pos == NULL)
if (pos == nullptr)
push_front(a);
else
{
Expand Down
Loading