Updates to configuration API.
authorBrian Aker <brian@tangent.org>
Tue, 22 Mar 2011 20:08:58 +0000 (13:08 -0700)
committerBrian Aker <brian@tangent.org>
Tue, 22 Mar 2011 20:08:58 +0000 (13:08 -0700)
14 files changed:
clients/memparse.cc
libmemcached/array.c
libmemcached/array.h
libmemcached/behavior.c
libmemcached/memcached.c
libmemcached/memcached.h
libmemcached/options.cc
libmemcached/options.h
libmemcached/options/parser.yy
libmemcached/options/scanner.l
libmemcached/parse.h
tests/mem_functions.c
tests/parser.cc
tests/parser.h

index c2be258ec828ea95e71703378a81f5b11034d81b..704d7b5272fd9ca57943adece5dbdce276b214f4 100644 (file)
@@ -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)
index 657bcdad96840c3909fe5ccce3c93c41e8637250..2412369e2a4199d81815d5d04cad496b4602ddcd 100644 (file)
@@ -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)
index 08938494f7a7d24e427a1780894c093aacadd2a8..ddc97d5a5e9a26a5dd3130b3b8ff932a66e3f051 100644 (file)
@@ -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<int>(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<int>(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
index 5116b645fe783efabb5d817a98c03ef256e086ca..055de192de28f38652622b36bb87a6eba488f3e6 100644 (file)
@@ -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 */
index a1f4b379ff5cf79804e97df87b3e53acd99d2d89..bc335dd8bf6139d96b27f853643bf57e0dce88de 100644 (file)
@@ -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)
index 65b3b048bfe96c175e4243933f67c118e56b315c..193eb33c723f8300c5102e962b7f0f31ada1b73a 100644 (file)
@@ -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);
index fefcb57dc1d81ef64923d38e3fdefcd73de2dce8..cd6d28d4eb2e08d8a0cbaa11f7fa26f66b6b34b2 100644 (file)
 
 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);
 }
index b1b9b92ad67271a4657afd22c3086a9b699b545d..f06ae566d13591c2f5e0d72aaa28b89ff2be69ad 100644 (file)
@@ -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
 }
index 5b1406283541add6e8479df7e107d15b9c375f06..00ad06312e06c290caf731d5007e0eb5ece53836 100644 (file)
@@ -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
         ;
 
index f5d09e7a3aaa1e1755f5bc3cf4ab2470d7c1f830..71f45d79cb663c6c3a472d6aa78299101174f0c0 100644 (file)
@@ -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; }
index 45a5d746946eb95d9409893bb3eb2c7dff3b09f8..a91f769d1b0191c03e98d47af6e103eebd1c0027 100644 (file)
@@ -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__ */
index 4b961911ddbe810ffa0a5fc455ebcd5a07862df0..b2e8be2bb84d48d9d20755f058ed1717cf9460ec 100644 (file)
@@ -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 },
index 5a8187552638b1d35b2c25311d2372ed3abb0e02..b69e4486ee4fcadd23655be88dfc70e4f5e707ce 100644 (file)
@@ -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);
 
index d3dfbf64567166e71bc4380919f698e445308635..895a3d58d88037c556acd7264917438c552817b9 100644 (file)
@@ -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