diff --git a/server/MaxScale_template.cnf b/server/MaxScale_template.cnf index a3f44ebf1..a2f961c79 100644 --- a/server/MaxScale_template.cnf +++ b/server/MaxScale_template.cnf @@ -184,7 +184,7 @@ replace=select # max_slave_replication_lag= # # Valid router modules currently are: -# readwritesplit, readconnroute, debugcli and CLI +# readwritesplit, readconnroute, dbshard, debugcli and CLI # ## Examples: @@ -208,6 +208,13 @@ passwd=mypwd #router_options=slave_selection_criteria= #filters=fetch|qla +[DBShard Router] +type=service +router=dbshard +servers=server1,server2 +user=maxuser +passwd=maxpwd + [HTTPD Router] type=service router=testroute @@ -263,6 +270,12 @@ protocol=MySQLClient port=4006 #socket=/tmp/rwsplit.sock +[DBShard Listener] +type=listener +service=DBShard Router +protocol=MySQLClient +port=4010 + [Debug Listener] type=listener service=Debug Interface diff --git a/server/core/config.c b/server/core/config.c index 737781d7f..8461b8b34 100644 --- a/server/core/config.c +++ b/server/core/config.c @@ -282,13 +282,18 @@ int error_count = 0; char *weightby; char *version_string; bool is_rwsplit = false; - + bool is_dbshard = false; + char *allow_localhost_match_wildcard_host; + obj->element = service_alloc(obj->object, router); user = config_get_value(obj->parameters, "user"); auth = config_get_value(obj->parameters, "passwd"); enable_root_user = config_get_value( obj->parameters, "enable_root_user"); + allow_localhost_match_wildcard_host = + config_get_value(obj->parameters, + "localhost_match_wildcard_host"); weightby = config_get_value(obj->parameters, "weightby"); version_string = config_get_value(obj->parameters, @@ -298,9 +303,10 @@ int error_count = 0; { is_rwsplit = true; } - - char *allow_localhost_match_wildcard_host = - config_get_value(obj->parameters, "localhost_match_wildcard_host"); + else if (strncasecmp(router, "dbshard", strlen("dbshard")+1) == 0) + { + is_dbshard = true; + } if (obj->element == NULL) /*< if module load failed */ { @@ -315,20 +321,31 @@ int error_count = 0; continue; /*< process next obj */ } - if (version_string) { - ((SERVICE *)(obj->element))->version_string = strdup(version_string); - } else { - if (gateway.version_string) - ((SERVICE *)(obj->element))->version_string = strdup(gateway.version_string); + if (version_string != NULL) + { + ((SERVICE *)(obj->element))->version_string = + strdup(version_string); + } + else + { + if (gateway.version_string != NULL) + { + ((SERVICE *)(obj->element))->version_string = + strdup(gateway.version_string); + } } - max_slave_conn_str = - config_get_value(obj->parameters, - "max_slave_connections"); - - max_slave_rlag_str = - config_get_value(obj->parameters, - "max_slave_replication_lag"); - + + if (is_rwsplit) + { + max_slave_conn_str = + config_get_value(obj->parameters, + "max_slave_connections"); + + max_slave_rlag_str = + config_get_value(obj->parameters, + "max_slave_replication_lag"); + } + if (enable_root_user) serviceEnableRootUser( obj->element, @@ -347,9 +364,7 @@ int error_count = 0; if (obj->element && user && auth) { - serviceSetUser(obj->element, - user, - auth); + serviceSetUser(obj->element, user, auth); } else if (user && auth == NULL) { @@ -361,7 +376,7 @@ int error_count = 0; obj->object))); } /** Read, validate and set max_slave_connections */ - if (max_slave_conn_str != NULL) + if (is_rwsplit && max_slave_conn_str != NULL) { CONFIG_PARAMETER* param; bool succp; @@ -399,7 +414,7 @@ int error_count = 0; } } /** Read, validate and set max_slave_replication_lag */ - if (max_slave_rlag_str != NULL) + if (is_rwsplit && max_slave_rlag_str != NULL) { CONFIG_PARAMETER* param; bool succp; @@ -1293,10 +1308,14 @@ SERVER *server; version_string = config_get_value(obj->parameters, "version_string"); - allow_localhost_match_wildcard_host = config_get_value(obj->parameters, "localhost_match_wildcard_host"); + allow_localhost_match_wildcard_host = + config_get_value(obj->parameters, + "localhost_match_wildcard_host"); - if (version_string) { - if (service->version_string) { + if (version_string) + { + if (service->version_string) + { free(service->version_string); } service->version_string = strdup(version_string); diff --git a/server/modules/routing/dbshard/dbshard.c b/server/modules/routing/dbshard/dbshard.c index f415958bb..1ce8331d6 100644 --- a/server/modules/routing/dbshard/dbshard.c +++ b/server/modules/routing/dbshard/dbshard.c @@ -330,20 +330,21 @@ bool update_dbnames_hash(BACKEND** backends, HASHTABLE* hashtable) SERVER* server; int i, rc, numfields; + for(i = 0;backends[i];i++) + { + MYSQL* handle = mysql_init(NULL); + MYSQL_RES* result = NULL; + MYSQL_ROW row; + char *user,*pwd = NULL; - - for(i = 0;backends[i];i++){ - - MYSQL* handle = mysql_init(NULL); - MYSQL_RES* result = NULL; - MYSQL_ROW row; - char *user,*pwd = NULL; - - if(handle == NULL){ - LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,"Error: Failed to initialize MySQL handle."))); - return false; - } - + if(handle == NULL) + { + LOGIF(LE, (skygw_log_write_flush( + LOGFILE_ERROR, + "Error: Failed to initialize " + "MySQL handle."))); + return false; + } rc = 0; rc |= mysql_options(handle, MYSQL_OPT_CONNECT_TIMEOUT, @@ -360,41 +361,40 @@ bool update_dbnames_hash(BACKEND** backends, HASHTABLE* hashtable) rval = false; continue; } - - server = backends[i]->backend_server; ss_dassert(server != NULL); - if(server->monuser == NULL || server->monpw == NULL){ + if(server->monuser == NULL || server->monpw == NULL) + { LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error: No username or password defined for server '%s'.",server->unique_name))); + LOGFILE_ERROR, + "Error: No username or password " + "defined for server '%s'.", + server->unique_name))); rval = false; goto cleanup; } - /** Plain-text password used for authentication for now */ user = server->monuser; pwd = server->monpw; - if (mysql_real_connect(handle, - server->name, - user, - pwd, - NULL, - server->port, - NULL, - 0) == NULL) + server->name, + user, + pwd, + NULL, + server->port, + NULL, + 0) == NULL) { LOGIF(LE, (skygw_log_write_flush( - LOGFILE_ERROR, - "Error: Failed to connect to backend " - "server '%s': %d %s", - server->name, - mysql_errno(handle), - mysql_error(handle)))); + LOGFILE_ERROR, + "Error: Failed to connect to backend " + "server '%s': %d %s", + server->name, + mysql_errno(handle), + mysql_error(handle)))); rval = false; goto cleanup; } @@ -402,13 +402,14 @@ bool update_dbnames_hash(BACKEND** backends, HASHTABLE* hashtable) * The server was successfully connected to, proceed to query for database names */ - if((result = mysql_list_dbs(handle,NULL)) == NULL){ + if((result = mysql_list_dbs(handle,NULL)) == NULL) + { LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR, - "Error: Failed to retrieve databases from backend " - "server '%s': %d %s", - server->name, - mysql_errno(handle), - mysql_error(handle)))); + "Error: Failed to retrieve databases from backend " + "server '%s': %d %s", + server->name, + mysql_errno(handle), + mysql_error(handle)))); goto cleanup; } numfields = mysql_num_fields(result); @@ -450,6 +451,7 @@ bool update_dbnames_hash(BACKEND** backends, HASHTABLE* hashtable) if(hashtable_add(hashtable,dbnm,servnm) == 0) { + char* srvname; #ifdef SHARD_UPDATES { char* old_backend = (char*)hashtable_fetch(hashtable,dbnm); @@ -493,7 +495,7 @@ bool update_dbnames_hash(BACKEND** backends, HASHTABLE* hashtable) } #endif /*< SHARD_UPDATES */ /*Check if the failure was due to a duplicate value*/ - if(hashtable_fetch(hashtable,dbnm) == NULL) + if((srvname = hashtable_fetch(hashtable,dbnm)) == NULL) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, @@ -503,7 +505,13 @@ bool update_dbnames_hash(BACKEND** backends, HASHTABLE* hashtable) { LOGIF(LE, (skygw_log_write_flush( LOGFILE_ERROR, - "Error: Duplicate value found."))); + "Error : Conflicting " + "databases found. " + "Both \"%s\" and \"%s\" " + "have a database \"%s\".", + server->unique_name, + srvname, + dbnm))); } rval = false; free(dbnm); @@ -796,14 +804,16 @@ createInstance(SERVICE *service, char **options) router->servers[nservers]->backend_conn_count = 0; router->servers[nservers]->weight = 1; router->servers[nservers]->be_valid = false; - if(server->monuser == NULL) - { - router->servers[nservers]->backend_server->monuser = strdup(service->credentials.name); - } - if(server->monpw == NULL) - { - router->servers[nservers]->backend_server->monpw = strdup(service->credentials.authdata); - } + if(server->monuser == NULL && service->credentials.name != NULL) + { + router->servers[nservers]->backend_server->monuser = + strdup(service->credentials.name); + } + if(server->monpw == NULL && service->credentials.authdata != NULL) + { + router->servers[nservers]->backend_server->monpw = + strdup(service->credentials.authdata); + } #if defined(SS_DEBUG) router->servers[nservers]->be_chk_top = CHK_NUM_BACKEND; router->servers[nservers]->be_chk_tail = CHK_NUM_BACKEND; @@ -906,8 +916,9 @@ static void* newSession( spinlock_acquire(&router->lock); /** - * ??? tarvitaanko + * ??? tarvitaanko - ei vielä */ +#if 0 if (router->service->svc_config_version > router->dbshard_version) { /** re-read all parameters to rwsplit config structure */ @@ -919,7 +930,7 @@ static void* newSession( } /** Copy config struct from router instance */ client_rses->rses_config = router->dbshard_config; - +#endif spinlock_release(&router->lock); /** * Set defaults to session variables. @@ -985,9 +996,7 @@ static void* newSession( * Find a backend servers to connect to. * This command requires that rsession's lock is held. */ - succp = rses_begin_locked_router_action(client_rses); - - if(!succp) + if (!(succp = rses_begin_locked_router_action(client_rses))) { free(client_rses->rses_backend_ref); free(client_rses); @@ -2403,12 +2412,6 @@ static void bref_set_state( * @param router_nservers - in, use * Number of backend server pointers pointed to by b. * - * @param max_nslaves - in, use - * Upper limit for the number of slaves. Configuration parameter or default. - * - * @param max_slave_rlag - in, use - * Maximum allowed replication lag for any slave. Configuration parameter or default. - * * @param session - in, use * MaxScale session pointer used when connection to backend is established. * @@ -2437,7 +2440,7 @@ static bool connect_backend_servers( int servers_found = 0; int servers_connected = 0; int slaves_connected = 0; - int i,max_nservers = router_nservers; + int i; /* select_criteria_t select_criteria = LEAST_GLOBAL_CONNECTIONS; */ @@ -2488,9 +2491,10 @@ static bool connect_backend_servers( } } /*< log only */ /** - * Choose at least onr server from the list. + * Scan server list and connect each of them. None should fail or session + * can't be established. */ - for (i=0; i < router_nservers && servers_connected < max_nservers; i++) + for (i=0; i < router_nservers; i++) { BACKEND* b = backend_ref[i].bref_backend; @@ -2540,12 +2544,12 @@ static bool connect_backend_servers( bref_set_state(&backend_ref[i], BREF_IN_USE); /** - * Increase backend connection counter. - * Server's stats are _increased_ in - * dcb.c:dcb_alloc ! - * But decreased in the calling function - * of dcb_close. - */ + * Increase backend connection counter. + * Server's stats are _increased_ in + * dcb.c:dcb_alloc ! + * But decreased in the calling function + * of dcb_close. + */ atomic_add(&b->backend_conn_count, 1); } else