From 9da805a13af25708dcf567f15ea7c1acf31462f1 Mon Sep 17 00:00:00 2001 From: Brian Aker Date: Tue, 22 Mar 2011 13:08:58 -0700 Subject: [PATCH] Updates to configuration API. --- clients/memparse.cc | 2 +- libmemcached/array.c | 11 +++- libmemcached/array.h | 14 +++-- libmemcached/behavior.c | 5 +- libmemcached/memcached.c | 30 +++++++++-- libmemcached/memcached.h | 6 ++- libmemcached/options.cc | 97 ++++++++++++++++++++++++---------- libmemcached/options.h | 15 ++++-- libmemcached/options/parser.yy | 9 +++- libmemcached/options/scanner.l | 2 + libmemcached/parse.h | 5 +- tests/mem_functions.c | 6 ++- tests/parser.cc | 43 ++++++++++++--- tests/parser.h | 10 +++- 14 files changed, 191 insertions(+), 64 deletions(-) diff --git a/clients/memparse.cc b/clients/memparse.cc index c2be258e..704d7b52 100644 --- a/clients/memparse.cc +++ b/clients/memparse.cc @@ -54,7 +54,7 @@ int main(int argc, char *argv[]) memc= memcached_create(NULL); - memcached_return_t rc= memcached_parse_options(memc, argv[1], strlen(argv[1])); + memcached_return_t rc= memcached_parse_configuration(memc, argv[1], strlen(argv[1])); memcached_free(memc); if (rc != MEMCACHED_SUCCESS) diff --git a/libmemcached/array.c b/libmemcached/array.c index 657bcdad..2412369e 100644 --- a/libmemcached/array.c +++ b/libmemcached/array.c @@ -62,11 +62,20 @@ memcached_array_st *memcached_strcpy(memcached_st *memc, const char *str, size_t array->root= memc; array->size= str_length -1; // We don't count the NULL ending memcpy(array->c_str, str, str_length); - array->c_str[str_length +1]= 0; + array->c_str[str_length]= 0; return array; } +memcached_string_t memcached_array_to_string(memcached_array_st *array) +{ + memcached_string_t tmp; + tmp.c_str= array->c_str; + tmp.size= array->size; + + return tmp; +} + void memcached_array_free(memcached_array_st *array) { if (! array) diff --git a/libmemcached/array.h b/libmemcached/array.h index 08938494..ddc97d5a 100644 --- a/libmemcached/array.h +++ b/libmemcached/array.h @@ -56,13 +56,17 @@ size_t memcached_array_size(memcached_array_st *array); LIBMEMCACHED_LOCAL const char *memcached_array_string(memcached_array_st *array); +LIBMEMCACHED_LOCAL +memcached_string_t memcached_array_to_string(memcached_array_st *array); + #ifdef __cplusplus -#define memcached_print_array(X) static_cast(memcached_array_size(X)), memcached_array_string(X) -#else -#define memcached_print_array(X) (int)memcached_array_size((X)), memcached_array_string((X)) +} // extern "C" #endif - #ifdef __cplusplus -} // extern "C" +#define memcached_print_array(X) static_cast(memcached_array_size(X)), memcached_array_string(X) +#define memcached_param_array(X) memcached_array_string(X), memcached_array_size(X) +#else +#define memcached_print_array(X) (int)memcached_array_size((X)), memcached_array_string((X)) +#define memcached_param_array(X) memcached_array_string(X), memcached_array_size(X) #endif diff --git a/libmemcached/behavior.c b/libmemcached/behavior.c index 5116b645..055de192 100644 --- a/libmemcached/behavior.c +++ b/libmemcached/behavior.c @@ -228,8 +228,7 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr, } break; case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE: - ptr->flags.load_from_file= set_flag(data); - break; + return MEMCACHED_FAILURE; case MEMCACHED_BEHAVIOR_MAX: default: /* Shouldn't get here */ @@ -386,7 +385,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr, case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE: return ptr->flags.tcp_keepalive; case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE: - return ptr->flags.load_from_file; + return ptr->configure.filename ? true : false; case MEMCACHED_BEHAVIOR_MAX: default: WATCHPOINT_ASSERT(0); /* Programming mistake if it gets this far */ diff --git a/libmemcached/memcached.c b/libmemcached/memcached.c index a1f4b379..bc335dd8 100644 --- a/libmemcached/memcached.c +++ b/libmemcached/memcached.c @@ -35,7 +35,6 @@ static const memcached_st global_copy= { .use_udp= false, .verify_key= false, .tcp_keepalive= false, - .load_from_file= false, .ping_service= false } }; @@ -98,6 +97,7 @@ static inline bool _memcached_init(memcached_st *self) self->error_messages= NULL; self->prefix_key= NULL; + self->configure.filename= NULL; return true; } @@ -130,6 +130,12 @@ static void _free(memcached_st *ptr, bool release_st) #endif } + if (release_st) + { + memcached_array_free(ptr->configure.filename); + ptr->configure.filename= NULL; + } + if (memcached_is_allocated(ptr) && release_st) { libmemcached_free(ptr, ptr); @@ -183,21 +189,37 @@ memcached_st *memcached_create_with_options(const char *string, size_t length) if (! self) return NULL; - memcached_parse_options(self, string, length); + memcached_return_t rc; + if ((rc= memcached_parse_configuration(self, string, length)) != MEMCACHED_SUCCESS) + { + return self; + } + + if (memcached_parse_filename(self)) + { + rc= memcached_parse_configure_file(self, memcached_parse_filename(self), memcached_parse_filename_length(self)); + } return self; } -void memcached_reset(memcached_st *ptr) +memcached_return_t memcached_reset(memcached_st *ptr) { WATCHPOINT_ASSERT(ptr); if (! ptr) - return; + return MEMCACHED_INVALID_ARGUMENTS; bool stored_is_allocated= memcached_is_allocated(ptr); _free(ptr, false); memcached_create(ptr); memcached_set_allocated(ptr, stored_is_allocated); + + if (ptr->configure.filename) + { + return memcached_parse_configure_file(ptr, memcached_param_array(ptr->configure.filename)); + } + + return MEMCACHED_SUCCESS; } void memcached_servers_reset(memcached_st *ptr) diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h index 65b3b048..193eb33c 100644 --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@ -85,7 +85,6 @@ struct memcached_st { bool use_udp:1; bool verify_key:1; bool tcp_keepalive:1; - bool load_from_file:1; bool ping_service:1; } flags; memcached_server_distribution_t distribution; @@ -131,6 +130,9 @@ struct memcached_st { struct memcached_sasl_st sasl; struct memcached_error_st *error_messages; struct memcached_array_st *prefix_key; + struct { + struct memcached_array_st *filename; + } configure; struct { bool is_allocated:1; } options; @@ -154,7 +156,7 @@ LIBMEMCACHED_API void memcached_free(memcached_st *ptr); LIBMEMCACHED_API -void memcached_reset(memcached_st *ptr); +memcached_return_t memcached_reset(memcached_st *ptr); LIBMEMCACHED_API void memcached_reset_last_disconnected_server(memcached_st *ptr); diff --git a/libmemcached/options.cc b/libmemcached/options.cc index fefcb57d..cd6d28d4 100644 --- a/libmemcached/options.cc +++ b/libmemcached/options.cc @@ -42,32 +42,77 @@ int libmemcached_parse(type_st *, yyscan_t *); -memcached_return_t memcached_check_options(const char *option_string, size_t length, const char *error_buffer, size_t error_buffer_size) +const char *memcached_parse_filename(memcached_st *memc) { - memcached_st memc; - if (! memcached_create(&memc)) + return memcached_array_string(memc->configure.filename); +} + +size_t memcached_parse_filename_length(memcached_st *memc) +{ + return memcached_array_size(memc->configure.filename); +} + +static memcached_return_t _parse_file_options(memcached_st *self, memcached_string_t *filename) +{ + FILE *fp= fopen(filename->c_str, "r"); + if (! fp) + return memcached_set_errno(self, errno, NULL); + + char buffer[BUFSIZ]; + memcached_return_t rc= MEMCACHED_INVALID_ARGUMENTS; + while (fgets(buffer, sizeof(buffer), fp)) + { + size_t length= strlen(buffer); + + if (length == 1 and buffer[0] == '\n') + continue; + + rc= memcached_parse_configuration(self, buffer, length); + if (rc != MEMCACHED_SUCCESS) + break; + } + fclose(fp); + + return rc; +} + +memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, const char *error_buffer, size_t error_buffer_size) +{ + memcached_st memc, *memc_ptr; + + if (! (memc_ptr= memcached_create(&memc))) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; - memcached_return_t rc= memcached_parse_options(&memc, option_string, length); + memcached_return_t rc= memcached_parse_configuration(memc_ptr, option_string, length); if (rc != MEMCACHED_SUCCESS && error_buffer && error_buffer_size) { - strncpy(error_buffer, error_buffer_size, memcached_last_error_message(&memc)); + strncpy(error_buffer, error_buffer_size, memcached_last_error_message(memc_ptr)); } - memcached_free(&memc); + if (rc== MEMCACHED_SUCCESS && memcached_behavior_get(memc_ptr, MEMCACHED_BEHAVIOR_LOAD_FROM_FILE)) + { + memcached_string_t filename= memcached_array_to_string(memc_ptr->configure.filename); + rc= _parse_file_options(memc_ptr, &filename); + + if (rc != MEMCACHED_SUCCESS && error_buffer && error_buffer_size) + { + strncpy(error_buffer, error_buffer_size, memcached_last_error_message(memc_ptr)); + } + } + + memcached_free(memc_ptr); return rc; } -memcached_return_t memcached_parse_options(memcached_st *self, char const *option_string, size_t length) +memcached_return_t memcached_parse_configuration(memcached_st *self, char const *option_string, size_t length) { type_st pp; - memset(&pp, 0, sizeof(type_st)); WATCHPOINT_ASSERT(self); if (! self) - return MEMCACHED_INVALID_ARGUMENTS; + return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, NULL); pp.buf= option_string; pp.memc= self; @@ -83,27 +128,23 @@ memcached_return_t memcached_parse_options(memcached_st *self, char const *optio return MEMCACHED_SUCCESS; } -memcached_return_t memcached_parse_file_options(memcached_st *self, const char *filename) +void memcached_set_configuration_file(memcached_st *self, const char *filename, size_t filename_length) { - FILE *fp= fopen(filename, "r"); - - if (! fp) - return memcached_set_errno(self, errno, NULL); + memcached_array_free(self->configure.filename); + self->configure.filename= memcached_strcpy(self, filename, filename_length); +} - char buffer[BUFSIZ]; - memcached_return_t rc= MEMCACHED_INVALID_ARGUMENTS; - while (fgets(buffer, sizeof(buffer), fp)) - { - size_t length= strlen(buffer); - - if (length == 1 and buffer[0] == '\n') - continue; +memcached_return_t memcached_parse_configure_file(memcached_st *self, const char *filename, size_t filename_length) +{ + if (! self) + return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, NULL); - rc= memcached_parse_options(self, buffer, length); - if (rc != MEMCACHED_SUCCESS) - break; - } - fclose(fp); + if (! filename || filename_length == 0) + return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, NULL); + + memcached_string_t tmp; + tmp.c_str= filename; + tmp.size= filename_length; - return rc; + return _parse_file_options(self, &tmp); } diff --git a/libmemcached/options.h b/libmemcached/options.h index b1b9b92a..f06ae566 100644 --- a/libmemcached/options.h +++ b/libmemcached/options.h @@ -42,13 +42,22 @@ extern "C" { #endif LIBMEMCACHED_API - memcached_return_t memcached_check_options(const char *option_string, size_t length, const char *error_buffer, size_t error_buffer_size); + memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, const char *error_buffer, size_t error_buffer_size); LIBMEMCACHED_API - memcached_return_t memcached_parse_options(memcached_st *ptr, const char *option_string, size_t length); + memcached_return_t memcached_parse_configuration(memcached_st *ptr, const char *option_string, size_t length); LIBMEMCACHED_API - memcached_return_t memcached_parse_file_options(memcached_st *ptr, const char *filename); + memcached_return_t memcached_parse_configure_file(memcached_st *ptr, const char *filename, size_t filename_length); + +LIBMEMCACHED_API + void memcached_set_configuration_file(memcached_st *self, const char *filename, size_t filename_length); + +LIBMEMCACHED_API + const char *memcached_parse_filename(memcached_st *memc); + +LIBMEMCACHED_LOCAL + size_t memcached_parse_filename_length(memcached_st *memc); #ifdef __cplusplus } diff --git a/libmemcached/options/parser.yy b/libmemcached/options/parser.yy index 5b140628..00ad0631 100644 --- a/libmemcached/options/parser.yy +++ b/libmemcached/options/parser.yy @@ -57,11 +57,12 @@ inline void libmemcached_error(YYLTYPE *locp, type_st *parser, yyscan_t *scanner %start statement %verbose +%token COMMENT +%token CONFIGURE_FILE +%token EMPTY_LINE %token SERVER %token SERVERS %token UNKNOWN -%token COMMENT -%token EMPTY_LINE %token DASH_OPTION @@ -160,6 +161,10 @@ expression: | SERVERS '=' server_list { } + | CONFIGURE_FILE '=' string + { + memcached_set_configuration_file(parser->memc, $3.c_str, $3.length); + } | behaviors ; diff --git a/libmemcached/options/scanner.l b/libmemcached/options/scanner.l index f5d09e7a..71f45d79 100644 --- a/libmemcached/options/scanner.l +++ b/libmemcached/options/scanner.l @@ -100,6 +100,8 @@ BUFFER_REQUESTS { return BUFFER_REQUESTS; } BUFFER-REQUESTS { return BUFFER_REQUESTS; } CACHE_LOOKUPS { return CACHE_LOOKUPS; } CACHE-LOOKUPS { return CACHE_LOOKUPS; } +CONFIGURE_FILE { return CONFIGURE_FILE; } +CONFIGURE-FILE { return CONFIGURE_FILE; } CONNECT_TIMEOUT { return CONNECT_TIMEOUT; } CONNECT-TIMEOUT { return CONNECT_TIMEOUT; } CORK { return _CORK; } diff --git a/libmemcached/parse.h b/libmemcached/parse.h index 45a5d746..a91f769d 100644 --- a/libmemcached/parse.h +++ b/libmemcached/parse.h @@ -9,8 +9,7 @@ * */ -#ifndef __LIBMEMCACHED_PARSE_H__ -#define __LIBMEMCACHED_PARSE_H__ +#pragma once #ifdef __cplusplus extern "C" { @@ -22,5 +21,3 @@ memcached_server_list_st memcached_servers_parse(const char *server_strings); #ifdef __cplusplus } #endif - -#endif /* __LIBMEMCACHED_PARSE_H__ */ diff --git a/tests/mem_functions.c b/tests/mem_functions.c index 4b961911..b2e8be2b 100644 --- a/tests/mem_functions.c +++ b/tests/mem_functions.c @@ -6318,10 +6318,12 @@ test_st error_conditions[] ={ test_st parser_tests[] ={ {"behavior", 0, (test_callback_fn)behavior_parser_test }, {"boolean_options", 0, (test_callback_fn)parser_boolean_options_test }, + {"configure_file", 0, (test_callback_fn)memcached_create_with_options_with_filename }, {"distribtions", 0, (test_callback_fn)parser_distribution_test }, {"hash", 0, (test_callback_fn)parser_hash_test }, - {"memcached_check_options", 0, (test_callback_fn)memcached_check_options_test }, - {"memcached_parse_file_options", 0, (test_callback_fn)memcached_parse_file_options_test }, + {"libmemcached_check_configuration", 0, (test_callback_fn)libmemcached_check_configuration_test }, + {"libmemcached_check_configuration_with_filename", 0, (test_callback_fn)libmemcached_check_configuration_with_filename_test }, + {"memcached_parse_configure_file", 0, (test_callback_fn)memcached_parse_configure_file_test }, {"number_options", 0, (test_callback_fn)parser_number_options_test }, {"prefix_key", 0, (test_callback_fn)parser_key_prefix_test }, {"server", 0, (test_callback_fn)server_test }, diff --git a/tests/parser.cc b/tests/parser.cc index 5a818755..b69e4486 100644 --- a/tests/parser.cc +++ b/tests/parser.cc @@ -246,7 +246,7 @@ static test_return_t _test_option(scanner_variable_t *scanner, bool test_true= t for (scanner_variable_t *ptr= scanner; ptr->type != NIL; ptr++) { memcached_return_t rc; - rc= memcached_parse_options(memc, ptr->option.c_str, ptr->option.size); + rc= memcached_parse_configuration(memc, ptr->option.c_str, ptr->option.size); if (test_true) { test_true_got(rc == MEMCACHED_SUCCESS, memcached_last_error_message(memc)); @@ -333,7 +333,7 @@ test_return_t parser_key_prefix_test(memcached_st *junk) return _test_option(distribution_strings); } -test_return_t memcached_parse_file_options_test(memcached_st *junk) +test_return_t memcached_parse_configure_file_test(memcached_st *junk) { (void)junk; memcached_st memc; @@ -341,23 +341,52 @@ test_return_t memcached_parse_file_options_test(memcached_st *junk) test_true(memc_ptr); - memcached_return_t rc= memcached_parse_file_options(memc_ptr, "support/example.cnf"); - test_true_got(rc == MEMCACHED_SUCCESS, rc == MEMCACHED_INVALID_ARGUMENTS ? memcached_last_error_message(&memc) : memcached_strerror(NULL, rc)); + memcached_return_t rc= memcached_parse_configure_file(memc_ptr, memcached_string_with_size("support/example.cnf")); + test_true_got(rc == MEMCACHED_SUCCESS, memcached_last_error_message(memc_ptr) ? memcached_last_error_message(memc_ptr) : memcached_strerror(NULL, rc)); memcached_free(memc_ptr); return TEST_SUCCESS; } -test_return_t memcached_check_options_test(memcached_st *junk) +test_return_t memcached_create_with_options_with_filename(memcached_st *junk) +{ + (void)junk; + + memcached_st *memc_ptr; + memc_ptr= memcached_create_with_options(STRING_WITH_LEN("--CONFIGURE-FILE=\"support/example.cnf\"")); + test_true(memc_ptr); + memcached_free(memc_ptr); + + return TEST_SUCCESS; +} + +test_return_t libmemcached_check_configuration_with_filename_test(memcached_st *junk) +{ + (void)junk; + memcached_return_t rc; + + rc= libmemcached_check_configuration(STRING_WITH_LEN("--CONFIGURE-FILE=\"support/example.cnf\""), NULL, 0); + test_true(rc == MEMCACHED_SUCCESS); + + rc= libmemcached_check_configuration(STRING_WITH_LEN("--CONFIGURE-FILE=support/example.cnf"), NULL, 0); + test_false(rc == MEMCACHED_SUCCESS); + + rc= libmemcached_check_configuration(STRING_WITH_LEN("--CONFIGURE-FILE=\"bad-path/example.cnf\""), NULL, 0); + test_true_got(rc == MEMCACHED_ERRNO, memcached_strerror(NULL, rc)); + + return TEST_SUCCESS; +} + +test_return_t libmemcached_check_configuration_test(memcached_st *junk) { (void)junk; memcached_return_t rc; - rc= memcached_check_options(STRING_WITH_LEN("--server=localhost"), NULL, 0); + rc= libmemcached_check_configuration(STRING_WITH_LEN("--server=localhost"), NULL, 0); test_true(rc == MEMCACHED_SUCCESS); - rc= memcached_check_options(STRING_WITH_LEN("--dude=localhost"), NULL, 0); + rc= libmemcached_check_configuration(STRING_WITH_LEN("--dude=localhost"), NULL, 0); test_false(rc == MEMCACHED_SUCCESS); test_true(rc == MEMCACHED_PARSE_ERROR); diff --git a/tests/parser.h b/tests/parser.h index d3dfbf64..895a3d58 100644 --- a/tests/parser.h +++ b/tests/parser.h @@ -68,14 +68,20 @@ LIBTEST_INTERNAL_API test_return_t parser_key_prefix_test(memcached_st *junk); LIBTEST_INTERNAL_API -test_return_t memcached_parse_file_options_test(memcached_st *junk); +test_return_t memcached_parse_configure_file_test(memcached_st *junk); LIBTEST_INTERNAL_API - test_return_t memcached_check_options_test(memcached_st *junk); + test_return_t libmemcached_check_configuration_test(memcached_st *junk); LIBTEST_INTERNAL_API test_return_t memcached_create_with_options_test(memcached_st *junk); +LIBTEST_INTERNAL_API + test_return_t memcached_create_with_options_with_filename(memcached_st *junk); + +LIBTEST_INTERNAL_API + test_return_t libmemcached_check_configuration_with_filename_test(memcached_st *junk); + #ifdef __cplusplus } #endif -- 2.30.2