Server list handling functions consistency

The functions handling servers lists now act with a bit more
consistency, always returning the array size instead of NULL-
terminating arrays.
This commit is contained in:
Esa Korhonen
2017-03-16 14:13:51 +02:00
parent bbcfe98651
commit 558a264e6d
5 changed files with 84 additions and 46 deletions

View File

@ -206,15 +206,33 @@ struct service* config_get_service(const MXS_CONFIG_PARAMETER *params, const cha
struct server* config_get_server(const MXS_CONFIG_PARAMETER *params, const char *key); struct server* config_get_server(const MXS_CONFIG_PARAMETER *params, const char *key);
/** /**
* @brief Get an array of servers. The caller should free the returned array, but not * @brief Get an array of servers. The caller should free the produced array,
* the array elements. * but not the array elements.
* *
* @param params List of configuration parameters * @param params List of configuration parameters
* @param key Parameter name * @param key Parameter name
* * @param output Where to save the output
* @return Pointer to a null-terminated array of servers, or null if none found. * @return How many servers were found, equal to output array size
*/ */
struct server** config_get_serverlist(const MXS_CONFIG_PARAMETER *params, const char *key); int config_get_server_list(const MXS_CONFIG_PARAMETER *params, const char *key,
struct server*** output);
/**
* Parse a list of server names and write the results in an array of strings
* with one server name in each. The output array and its elements should be
* deallocated by the caller. The server names are not checked to be actual
* configured servers.
*
* The output array may contain more elements than the the value returned, but these
* extra elements are null and in the end of the array. If no server names were
* parsed or if an error occurs, nothing is written to the output parameter.
*
* @param servers A list of server names
* @param output_array Where to save the output
* @return How many servers were found and set into the array. 0 on error or if
* none were found.
*/
int config_parse_server_list(const char *servers, char ***output_array);
/** /**
* @brief Get copy of parameter value if it is defined * @brief Get copy of parameter value if it is defined

View File

@ -256,7 +256,7 @@ bool server_remove_parameter(SERVER *server, const char *name);
extern int server_free(SERVER *server); extern int server_free(SERVER *server);
extern SERVER *server_find_by_unique_name(const char *name); extern SERVER *server_find_by_unique_name(const char *name);
extern SERVER** server_find_by_unique_names(char **server_names, int size); extern int server_find_by_unique_names(char **server_names, int size, SERVER*** output);
extern SERVER *server_find(const char *servname, unsigned short port); extern SERVER *server_find(const char *servname, unsigned short port);
extern char *server_status(const SERVER *); extern char *server_status(const SERVER *);
extern void server_clear_set_status(SERVER *server, int specified_bits, int bits_to_set); extern void server_clear_set_status(SERVER *server, int specified_bits, int bits_to_set);

View File

@ -1057,22 +1057,45 @@ SERVER* config_get_server(const MXS_CONFIG_PARAMETER *params, const char *key)
return server_find_by_unique_name(value); return server_find_by_unique_name(value);
} }
SERVER** config_get_serverlist(const MXS_CONFIG_PARAMETER *params, const char *key) int config_get_server_list(const MXS_CONFIG_PARAMETER *params, const char *key,
SERVER*** output)
{ {
const char *value = config_get_value_string(params, key); const char *value = config_get_value_string(params, key);
char **server_names = NULL; char **server_names = NULL;
SERVER **servers = NULL; int found = 0;
int n_names = config_parse_server_list(value, &server_names); const int n_names = config_parse_server_list(value, &server_names);
if (n_names > 0) if (n_names > 0)
{ {
servers = server_find_by_unique_names(server_names, n_names); SERVER** servers;
found = server_find_by_unique_names(server_names, n_names, &servers);
for (int i = 0; i < n_names; i++) for (int i = 0; i < n_names; i++)
{ {
MXS_FREE(server_names[i]); MXS_FREE(server_names[i]);
} }
MXS_FREE(server_names); MXS_FREE(server_names);
if (found)
{
/* Fill in the result array */
SERVER** result = MXS_CALLOC(found, sizeof(SERVER*));
if (result)
{
int res_ind = 0;
for (int i = 0; i < n_names; i++)
{
if (servers[i])
{
result[res_ind] = servers[i];
res_ind++;
} }
return servers; }
*output = result;
ss_dassert(found == res_ind);
}
MXS_FREE(servers);
}
}
return found;
} }
char* config_copy_string(const MXS_CONFIG_PARAMETER *params, const char *key) char* config_copy_string(const MXS_CONFIG_PARAMETER *params, const char *key)
@ -3470,7 +3493,7 @@ bool config_param_is_valid(const MXS_MODULE_PARAM *params, const char *key,
return valid; return valid;
} }
static int config_parse_server_list(const char *servers, char ***output_array) int config_parse_server_list(const char *servers, char ***output_array)
{ {
ss_dassert(servers); ss_dassert(servers);
@ -3486,7 +3509,7 @@ static int config_parse_server_list(const char *servers, char ***output_array)
char **results = MXS_CALLOC(out_arr_size, sizeof(char*)); char **results = MXS_CALLOC(out_arr_size, sizeof(char*));
if (!results) if (!results)
{ {
return -1; return 0;
} }
/* Parse the server names from the list. They are separated by ',' and will /* Parse the server names from the list. They are separated by ',' and will
@ -3531,8 +3554,10 @@ static int config_parse_server_list(const char *servers, char ***output_array)
if (output_ind == 0) if (output_ind == 0)
{ {
MXS_FREE(results); MXS_FREE(results);
results = NULL;
} }
else
{
*output_array = results; *output_array = results;
}
return output_ind; return output_ind;
} }

View File

@ -111,15 +111,4 @@ SSL_LISTENER *make_ssl_structure(CONFIG_CONTEXT *obj, bool require_cert, int *er
*/ */
bool config_have_required_ssl_params(CONFIG_CONTEXT *obj); bool config_have_required_ssl_params(CONFIG_CONTEXT *obj);
/**
* Parses a list of server names and writes the results in an array of strings
* with one server in each. The output array and its elements should be deallocated
* by the caller. The server names are not checked to be valid servers.
*
* @param servers A list of server names.
* @param output_array Save location for the array of server names. Set to null if none found.
* @return How many servers were found and set into the array.
*/
static int config_parse_server_list(const char *servers, char ***output_array);
MXS_END_DECLS MXS_END_DECLS

View File

@ -296,39 +296,45 @@ SERVER * server_find_by_unique_name(const char *name)
return server; return server;
} }
/** /**
* Find several servers with the names specified in an array with a given size. * Find several servers with the names specified in an array with a given size.
* The returned array (but not the elements) should be freed by the caller, and * The returned array (but not the elements) should be freed by the caller.
* is null-terminated. * If no valid server names were found or in case of error, nothing is written
* to the output parameter.
* *
* @param servers An array of server names * @param servers An array of server names
* @param size number of elements in the server names array * @param size Number of elements in the input server names array, equal to output
* @return A null-terminated array of SERVERs. May contain less elements than * size if any servers are found.
* requested if some server names are not found. * @param output Where to save the output. Contains null elements for invalid server
* names. If all were invalid, the output is left untouched.
* @return Number of valid server names found
*/ */
SERVER** server_find_by_unique_names(char **server_names, int size) int server_find_by_unique_names(char **server_names, int size, SERVER*** output)
{ {
ss_dassert(server_names); ss_dassert(server_names && (size > 0));
SERVER **results = MXS_CALLOC(size + 1, sizeof(SERVER*)); // +1 for null SERVER **results = MXS_CALLOC(size, sizeof(SERVER*));
if (!results) if (!results)
{ {
return NULL; return 0;
} }
int res_ind = 0; int found = 0;
for (int i = 0; server_names[i] != NULL; i++) for (int i = 0; i < size; i++)
{ {
SERVER *serv = server_find_by_unique_name(server_names[i]); results[i] = server_find_by_unique_name(server_names[i]);
if (serv) found += (results[i]) ? 1 : 0;
}
if (found)
{ {
results[res_ind] = serv; *output = results;
res_ind++;
} }
else
{
MXS_FREE(results);
} }
return results; return found;
} }
/** /**