Server status changes now happen under a lock

MXS-873 To prevent monitors and MaxAdmin from interfering with each other,
changes to the server status flags now happen under a lock. To avoid
interfering with monitor logic, the monitors now acquire locks to all
of their servers at the start of the monitor loop and release them
before sleeping.
This commit is contained in:
ekorh475
2016-12-07 14:52:46 +02:00
parent 162ae04d20
commit 259e944b3d
10 changed files with 135 additions and 65 deletions

View File

@ -671,48 +671,50 @@ server_status(SERVER *server)
{
return NULL;
}
unsigned int server_status = server->status;
status[0] = 0;
if (server->status & SERVER_MAINT)
if (server_status & SERVER_MAINT)
{
strcat(status, "Maintenance, ");
}
if (server->status & SERVER_MASTER)
if (server_status & SERVER_MASTER)
{
strcat(status, "Master, ");
}
if (server->status & SERVER_RELAY_MASTER)
if (server_status & SERVER_RELAY_MASTER)
{
strcat(status, "Relay Master, ");
}
if (server->status & SERVER_SLAVE)
if (server_status & SERVER_SLAVE)
{
strcat(status, "Slave, ");
}
if (server->status & SERVER_JOINED)
if (server_status & SERVER_JOINED)
{
strcat(status, "Synced, ");
}
if (server->status & SERVER_NDB)
if (server_status & SERVER_NDB)
{
strcat(status, "NDB, ");
}
if (server->status & SERVER_SLAVE_OF_EXTERNAL_MASTER)
if (server_status & SERVER_SLAVE_OF_EXTERNAL_MASTER)
{
strcat(status, "Slave of External Server, ");
}
if (server->status & SERVER_STALE_STATUS)
if (server_status & SERVER_STALE_STATUS)
{
strcat(status, "Stale Status, ");
}
if (server->status & SERVER_MASTER_STICKINESS)
if (server_status & SERVER_MASTER_STICKINESS)
{
strcat(status, "Master Stickiness, ");
}
if (server->status & SERVER_AUTH_ERROR)
if (server_status & SERVER_AUTH_ERROR)
{
strcat(status, "Auth Error, ");
}
if (server->status & SERVER_RUNNING)
if (server_status & SERVER_RUNNING)
{
strcat(status, "Running");
}
@ -724,13 +726,13 @@ server_status(SERVER *server)
}
/**
* Set a status bit in the server
* Set a status bit in the server without locking
*
* @param server The server to update
* @param bit The bit to set for the server
*/
void
server_set_status(SERVER *server, int bit)
server_set_status_nolock(SERVER *server, int bit)
{
server->status |= bit;
@ -745,6 +747,8 @@ server_set_status(SERVER *server, int bit)
* Set one or more status bit(s) from a specified set, clearing any others
* in the specified set
*
* @attention This function does no locking
*
* @param server The server to update
* @param bit The bit to set for the server
*/
@ -764,13 +768,13 @@ server_clear_set_status(SERVER *server, int specified_bits, int bits_to_set)
}
/**
* Clear a status bit in the server
* Clear a status bit in the server without locking
*
* @param server The server to update
* @param bit The bit to clear for the server
*/
void
server_clear_status(SERVER *server, int bit)
server_clear_status_nolock(SERVER *server, int bit)
{
server->status &= ~bit;
}
@ -778,6 +782,8 @@ server_clear_status(SERVER *server, int bit)
/**
* Transfer status bitstring from one server to another
*
* @attention This function does no locking
*
* @param dest_server The server to be updated
* @param source_server The server to provide the new bit string
*/
@ -1071,10 +1077,8 @@ bool server_set_version_string(SERVER* server, const char* string)
if (string)
{
spinlock_acquire(&server->lock);
char* old = server->server_string;
server->server_string = (char*)string;
spinlock_release(&server->lock);
MXS_FREE(old);
}
else
@ -1254,3 +1258,31 @@ SERVER* server_find_destroyed(const char *name, const char *protocol,
return server;
}
/**
* Set a status bit in the server under a lock. This ensures synchronization
* with the server monitor thread. Calling this inside the monitor will likely
* cause a deadlock.
*
* @param server The server to update
* @param bit The bit to set for the server
*/
void server_set_status(SERVER *server, int bit)
{
spinlock_acquire(&server->lock);
server_set_status_nolock(server, bit);
spinlock_release(&server->lock);
}
/**
* Clear a status bit in the server under a lock. This ensures synchronization
* with the server monitor thread. Calling this inside the monitor will likely
* cause a deadlock.
*
* @param server The server to update
* @param bit The bit to clear for the server
*/
void server_clear_status(SERVER *server, int bit)
{
spinlock_acquire(&server->lock);
server_clear_status_nolock(server, bit);
spinlock_release(&server->lock);
}