Skip to content

Commit

Permalink
Merge pull request #511 from sysown/498_implement_set_command
Browse files Browse the repository at this point in the history
#498 implement set command
  • Loading branch information
renecannao committed Mar 11, 2016
2 parents a782f77 + 88ec03d commit fbaca93
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 39 deletions.
10 changes: 10 additions & 0 deletions doc/global_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ Also, there are 2 types of global variables, depending on which part of ProxySQL

These global variables are stored in a per-thread fashion inside of the proxy in order to speed up access to them, as they are used extremely frequently. They control the behaviour of the proxy in terms of memory footprint or the number of connections accepted, and other essential aspects. Whenever a `LOAD MYSQL VARIABLES TO RUNTIME` command is issued (see the [configuration system documentation](https://github.com/sysown/proxysql-0.2/blob/master/doc/configuration_system.md) for details on that command), all the threads using the variables are notified that they have to update their values.

To change the value of a global variable either use an `UPDATE` statement:
```
UPDATE global_variables SET variable_value=1900 WHERE variable_name='admin-refresh_interval';
```
or the shorter `SET` statement, similar to MySQL's:
```
SET admin-refresh_interval = 1700;
SET admin-version = '1.1.1beta8';
```

Next, we're going to explain each type of variable in detail.

### `admin-admin_credentials`
Expand Down
3 changes: 3 additions & 0 deletions doc/internal/global_variables.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ either very simple, or managed by a simple API.

Trying to make a standard API, the proposed functions are:
virtual char **get_variables_list() {return NULL;}
virtual bool has_variable(char *name) {return false;}
virtual char *get_variable(char *name) {return NULL;};
virtual bool set_variable(char *name, char *value) {return false;};
virtual void commit() {};
Expand All @@ -14,6 +15,8 @@ Trying to make a standard API, the proposed functions are:
In order:
- get_variables_list() returns an array of pointer to variables name, where the
last element is NULL;
- has_variable() returns true if the given name is the name of one of the module
variables;
- get_variable() returns the value of a specific variable. If the variable was
not previously set, the module should return the default value. If the
variable doesn't exist, NULL should be returned;
Expand Down
1 change: 1 addition & 0 deletions include/MySQL_Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ class MySQL_Threads_Handler
char *get_variable(char *name);
bool set_variable(char *name, char *value);
char **get_variables_list();
bool has_variable(const char * name);

MySQL_Threads_Handler();
~MySQL_Threads_Handler();
Expand Down
1 change: 1 addition & 0 deletions include/gen_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,3 +153,4 @@ bool Proxy_file_exists(const char *);
bool Proxy_file_regular(const char *);

int remove_spaces(const char *);
char *trim_spaces_in_place(char *str);
1 change: 1 addition & 0 deletions include/proxysql_admin.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class ProxySQL_Admin {
bool init();
bool get_read_only() { return variables.admin_read_only; }
bool set_read_only(bool ro) { variables.admin_read_only=ro; return variables.admin_read_only; }
bool has_variable(const char *name);
void init_users();
void init_mysql_servers();
void init_mysql_query_rules();
Expand Down
34 changes: 23 additions & 11 deletions lib/MySQL_Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ int MySQL_Threads_Handler::listener_add(const char *iface) {
while(!__sync_bool_compare_and_swap(&thr->mypolls.pending_listener_add,0,rc)) {
usleep(100); // pause a bit
}
/*
/*
while(!__sync_bool_compare_and_swap(&thr->mypolls.pending_listener_change,0,1)) { cpu_relax_pa(); }
while(__sync_fetch_and_add(&thr->mypolls.pending_listener_change,0)==1) { cpu_relax_pa(); }
// spin_wrlock(&thr->thread_mutex);
Expand Down Expand Up @@ -323,7 +323,7 @@ int MySQL_Threads_Handler::listener_del(const char *iface) {
shutdown(fd,SHUT_RDWR);
close(fd);
}

return 0;
}

Expand Down Expand Up @@ -618,7 +618,7 @@ char * MySQL_Threads_Handler::get_variable(char *name) { // this is the public f
return strdup((variables.default_reconnect ? "true" : "false"));
}
return NULL;
}
}



Expand All @@ -630,7 +630,7 @@ bool MySQL_Threads_Handler::set_variable(char *name, char *value) { // this is t
// OUT:
// false: unable to change the variable value, either because doesn't exist, or because out of range, or read only
// true: variable value changed
//
//
if (!value) return false;
size_t vallen=strlen(value);

Expand Down Expand Up @@ -1175,6 +1175,18 @@ char ** MySQL_Threads_Handler::get_variables_list() {
return ret;
}

// Returns true if the given name is the name of an existing mysql variable
bool MySQL_Threads_Handler::has_variable(const char *name) {
size_t no_vars = sizeof(mysql_thread_variables_names) / sizeof(char *);
for (unsigned int i = 0; i < no_vars, mysql_thread_variables_names[i] != NULL; ++i) {
size_t var_len = strlen(mysql_thread_variables_names[i]);
if (strlen(name) == var_len && !strncmp(name, mysql_thread_variables_names[i], var_len)) {
return true;
}
}
return false;
}

void MySQL_Threads_Handler::print_version() {
fprintf(stderr,"Standard MySQL Threads Handler rev. %s -- %s -- %s\n", MYSQL_THREAD_VERSION, __FILE__, __TIMESTAMP__);
}
Expand Down Expand Up @@ -1345,8 +1357,8 @@ void MySQL_Thread::poll_listener_add(int sock) {
listener_DS->fd=sock;

proxy_debug(PROXY_DEBUG_NET,1,"Created listener %p for socket %d\n", listener_DS, sock);
//mypoll_add(&mypolls, POLLIN, sock, listener_DS);
mypolls.add(POLLIN, sock, listener_DS, monotonic_time());
//mypoll_add(&mypolls, POLLIN, sock, listener_DS);
mypolls.add(POLLIN, sock, listener_DS, monotonic_time());
}

void MySQL_Thread::poll_listener_del(int sock) {
Expand Down Expand Up @@ -1489,7 +1501,7 @@ void MySQL_Thread::run() {
proxy_debug(PROXY_DEBUG_NET,1,"Poll for DataStream=%p will be called with FD=%d and events=%d\n", mypolls.myds[n], mypolls.fds[n].fd, mypolls.fds[n].events);
}


spin_wrunlock(&thread_mutex);

while ((n=__sync_add_and_fetch(&mypolls.pending_listener_add,0))) { // spin here
Expand All @@ -1498,7 +1510,7 @@ void MySQL_Thread::run() {
// if (n==1) {
// __sync_add_and_fetch(&mypolls.pending_listener_change,1);
// }
}
}

if (mysql_thread___wait_timeout==0) {
// we should be going into PAUSE mode
Expand Down Expand Up @@ -1528,7 +1540,7 @@ void MySQL_Thread::run() {

spin_wrlock(&thread_mutex);
mypolls.poll_timeout=0; // always reset this to 0 . If a session needs a specific timeout, it will set this one

curtime=monotonic_time();
if (curtime > last_maintenance_time + 200000) { // hardcoded value for now
last_maintenance_time=curtime;
Expand Down Expand Up @@ -1646,15 +1658,15 @@ void MySQL_Thread::process_data_on_data_stream(MySQL_Data_Stream *myds, unsigned
myds->myconn->handler(mypolls.fds[n].revents);
}
}
if ( (mypolls.fds[n].events & POLLOUT)
if ( (mypolls.fds[n].events & POLLOUT)
&&
( (mypolls.fds[n].revents & POLLERR) || (mypolls.fds[n].revents & POLLHUP) )
) {
myds->set_net_failure();
}

myds->check_data_flow();


if (myds->active==FALSE) {
if (myds->sess->client_myds==myds) {
Expand Down
Loading

0 comments on commit fbaca93

Please sign in to comment.