This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, dyn-provider has been created
at 7b312ae175275f44da7922103c28220c85dbb55e (commit)
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/7b312ae175275f44da7922103c28220c85dbb55e
commit 7b312ae175275f44da7922103c28220c85dbb55e
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Dec 23 22:04:41 2010 +0100
remove functions and struct members that are no longer needed
* rest.c (free_ms): Remove function and all uses.
* setup.c (delete_provider): Remove function and sole use.
* setup.h (refcnt): Remove struct member and all uses.
* state_defs.h (cleanup, refcnt): Remove struct members.
Remove all uses.
* replica.c: Remove uses of the above.
diff --git a/replica.c b/replica.c
index 1910747..266da20 100644
--- a/replica.c
+++ b/replica.c
@@ -205,7 +205,6 @@ repl_worker (void *notused ATTRIBUTE_UNUSED)
error(0,0,"bad repl type %d (url=%s) skipped",
item->type, item->path);
}
- free_ms(item->ms);
free(item->path);
free(item);
/* No atomic dec without test? Lame. */
@@ -338,7 +337,6 @@ replicate (const char *url, size_t size, const char *policy, my_state
*ms)
item->server = prov;
item->size = size;
item->ms = ms;
- g_atomic_int_inc(&ms->refcnt);
pthread_mutex_lock(&queue_lock);
if (queue_tail) {
item->next = queue_tail->next;
@@ -388,7 +386,6 @@ replicate_namespace_action (const char *name, repl_t action, my_state
*ms)
}
item->server = (provider_t *)value;
item->ms = ms;
- g_atomic_int_inc(&ms->refcnt);
pthread_mutex_lock(&queue_lock);
if (queue_tail) {
item->next = queue_tail->next;
diff --git a/rest.c b/rest.c
index 059d7bf..dfa84b4 100644
--- a/rest.c
+++ b/rest.c
@@ -75,44 +75,6 @@ static const char *const (reserved_name[]) = {"_default",
"_new", "_policy", "_q
static const char *const (reserved_attr[]) = {"_bucket", "_date",
"_etag", "_key", "_loc", "_size", NULL};
static const char *const (reserved_bucket_name[]) = {"_new",
"_providers", NULL};
-void
-free_ms (my_state *ms)
-{
- if (!g_atomic_int_dec_and_test(&ms->refcnt)) {
- return;
- }
-
- if (ms->cleanup & CLEANUP_BUF_PTR) {
- free(ms->pipe.data_ptr);
- }
-
- if (ms->cleanup & CLEANUP_POST) {
- MHD_destroy_post_processor(ms->post);
- }
-
- if (ms->cleanup & CLEANUP_DICT) {
- g_hash_table_destroy(ms->dict);
- }
-
- if (ms->cleanup & CLEANUP_QUERY) {
- meta_query_stop(ms->query);
- }
-
- if (ms->cleanup & CLEANUP_TMPL) {
- free(ms->gen_ctx);
- }
-
- if (ms->cleanup & CLEANUP_URL) {
- free(ms->url);
- }
-
- if (ms->cleanup & CLEANUP_AQUERY) {
- meta_attr_stop(ms->aquery);
- }
-
- free(ms);
-}
-
static int
validate_put (struct MHD_Connection *conn)
{
@@ -203,7 +165,6 @@ simple_closer (void *ctx)
my_state *ms = ctx;
DPRINTF("%s: cleaning upn",__func__);
- free_ms(ms);
}
static void
@@ -266,7 +227,6 @@ proxy_get_cons (void *ctx, uint64_t pos, char *buf, size_t max)
pthread_join(ms->cache_th,NULL);
/* TBD: do something about cache failure? */
}
- free_ms(ms);
}
return done;
@@ -297,7 +257,6 @@ proxy_get_data (void *cctx, struct MHD_Connection *conn, const char
*url,
if (!ms->url) {
return MHD_NO;
}
- ms->cleanup |= CLEANUP_URL;
my_etag = meta_has_copy(ms->bucket,ms->key,me);
if (!my_etag) {
@@ -326,7 +285,6 @@ proxy_get_data (void *cctx, struct MHD_Connection *conn, const char
*url,
MHD_NO,MHD_NO);
MHD_queue_response(conn,MHD_HTTP_NOT_FOUND,resp);
MHD_destroy_response(resp);
- free_ms(ms);
return MHD_YES;
}
DPRINTF(" will fetch from %s:%un", master_host,master_port);
@@ -448,7 +406,6 @@ proxy_put_data (void *cctx, struct MHD_Connection *conn, const char
*url,
}
MHD_queue_response(conn,MHD_HTTP_FORBIDDEN,resp);
MHD_destroy_response(resp);
- free_ms(ms);
return MHD_YES;
}
ms->state = MS_NORMAL;
@@ -456,7 +413,6 @@ proxy_put_data (void *cctx, struct MHD_Connection *conn, const char
*url,
if (!ms->url) {
return MHD_NO;
}
- ms->cleanup |= CLEANUP_URL;
ms->size = 0;
pipe_init_shared(&ms->pipe,ms,1);
pp = pipe_init_private(&ms->pipe);
@@ -539,7 +495,6 @@ proxy_put_data (void *cctx, struct MHD_Connection *conn, const char
*url,
recheck_replication(ms,NULL);
rc = MHD_HTTP_OK;
}
- free_ms(ms);
resp = MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
if (!resp) {
free(etag);
@@ -587,7 +542,6 @@ proxy_get_attr (void *cctx, struct MHD_Connection *conn, const char
*url,
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
return MHD_YES;
}
@@ -613,7 +567,6 @@ proxy_put_attr (void *cctx, struct MHD_Connection *conn, const char
*url,
if (!ms->url) {
return MHD_NO;
}
- ms->cleanup |= CLEANUP_URL;
attrval = MHD_lookup_connection_value(conn,MHD_HEADER_KIND,
"X-redhat-value");
if (attrval) {
@@ -638,7 +591,6 @@ proxy_put_attr (void *cctx, struct MHD_Connection *conn, const char
*url,
return MHD_NO;
}
((char *)ms->pipe.data_ptr)[0] = '0';
- ms->cleanup |= CLEANUP_BUF_PTR;
}
(void)strncat(ms->pipe.data_ptr,data,*data_size);
/* TBD: check return value */
@@ -657,22 +609,15 @@ proxy_put_attr (void *cctx, struct MHD_Connection *conn, const char
*url,
MHD_queue_response(conn,MHD_HTTP_BAD_REQUEST,
resp);
MHD_destroy_response(resp);
- free_ms(ms);
return MHD_YES;
}
meta_set_value(ms->bucket,ms->key,ms->attr,ms->pipe.data_ptr);
- /* This might get stomped by replication. */
- if (ms->cleanup & CLEANUP_BUF_PTR) {
- free(ms->pipe.data_ptr);
- ms->cleanup &= ~CLEANUP_BUF_PTR;
- }
/*
* We should always re-replicate, because the replication
* policy might refer to this attr.
*/
DPRINTF("rereplicate (attr PUT)n");
recheck_replication(ms,NULL);
- free_ms(ms);
send_resp = 1;
}
@@ -744,7 +689,6 @@ proxy_query_func (void *ctx, uint64_t pos, char *buf, size_t max)
if (!ms->gen_ctx) {
return -1;
}
- ms->cleanup |= CLEANUP_TMPL;
len = tmpl_list_header(ms->gen_ctx);
if (!len) {
return -1;
@@ -787,7 +731,6 @@ proxy_query_func (void *ctx, uint64_t pos, char *buf, size_t max)
}
memcpy(buf,ms->gen_ctx->buf,len);
free(ms->gen_ctx);
- ms->cleanup &= ~CLEANUP_TMPL;
ms->gen_ctx = TMPL_CTX_DONE;
return len;
}
@@ -810,7 +753,6 @@ proxy_query (void *cctx, struct MHD_Connection *conn, const char
*url,
ms->state = MS_NORMAL;
ms->post = MHD_create_post_processor(conn,4096,
query_iterator,ms);
- ms->cleanup |= CLEANUP_POST;
}
else if (*data_size) {
MHD_post_process(ms->post,data,*data_size);
@@ -829,7 +771,6 @@ proxy_query (void *cctx, struct MHD_Connection *conn, const char
*url,
return MHD_NO;
}
((char *)ms->pipe.data_ptr)[0] = '0';
- ms->cleanup |= CLEANUP_BUF_PTR;
}
(void)strncat(ms->pipe.data_ptr,data,*data_size);
/* TBD: check return value */
@@ -840,7 +781,6 @@ proxy_query (void *cctx, struct MHD_Connection *conn, const char
*url,
return MHD_NO;
}
ms->query = meta_query_new(ms->bucket,NULL,ms->pipe.data_ptr);
- ms->cleanup |= CLEANUP_QUERY;
resp = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN,
65536, proxy_query_func, ms, simple_closer);
if (!resp) {
@@ -850,7 +790,6 @@ proxy_query (void *cctx, struct MHD_Connection *conn, const char
*url,
}
MHD_queue_response(conn,MHD_HTTP_OK,resp);
MHD_destroy_response(resp);
- free_ms(ms);
}
return MHD_YES;
@@ -872,7 +811,6 @@ proxy_list_objs (void *cctx, struct MHD_Connection *conn, const char
*url,
(void)data_size;
ms->query = meta_query_new((char *)ms->bucket,NULL,NULL);
- ms->cleanup |= CLEANUP_QUERY;
resp = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN,
65536, proxy_query_func, ms, simple_closer);
@@ -925,14 +863,12 @@ proxy_delete (void *cctx, struct MHD_Connection *conn, const char
*url,
resp = MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
if (!resp) {
- free_ms(ms);
return MHD_NO;
}
error (0, 0, "DELETE BUCKET: rc=%d", rc);
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
return MHD_YES;
}
@@ -971,7 +907,6 @@ root_blob_generator (void *ctx, uint64_t pos, char *buf, size_t max)
if (!ms->gen_ctx) {
return -1;
}
- ms->cleanup |= CLEANUP_TMPL;
ms->gen_ctx->base = host;
len = tmpl_root_header(ms->gen_ctx,"image_warehouse",VERSION);
if (!len) {
@@ -1022,7 +957,6 @@ root_blob_generator (void *ctx, uint64_t pos, char *buf, size_t max)
}
memcpy(buf,ms->gen_ctx->buf,len);
free(ms->gen_ctx);
- ms->cleanup &= ~CLEANUP_TMPL;
ms->gen_ctx = TMPL_CTX_DONE;
return len;
}
@@ -1045,11 +979,8 @@ proxy_api_root (void *cctx, struct MHD_Connection *conn, const char
*url,
ms->query = meta_query_new(NULL,"_default",NULL);
if (!ms->query) {
- free_ms(ms);
return MHD_NO;
}
- ms->cleanup |= CLEANUP_QUERY;
-
resp = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN,
65536, root_blob_generator, ms, simple_closer);
if (!resp) {
@@ -1188,10 +1119,8 @@ control_api_root (void *cctx, struct MHD_Connection *conn, const
char *url,
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
g_str_hash,g_str_equal,NULL,NULL);
- ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
post_iterator,ms->dict);
- ms->cleanup |= CLEANUP_POST;
return MHD_YES;
}
@@ -1231,7 +1160,6 @@ control_api_root (void *cctx, struct MHD_Connection *conn, const
char *url,
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
return MHD_YES;
}
@@ -1256,10 +1184,8 @@ proxy_bucket_post (void *cctx, struct MHD_Connection *conn, const
char *url,
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
g_str_hash,g_str_equal,NULL,NULL);
- ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
post_iterator,ms->dict);
- ms->cleanup |= CLEANUP_POST;
}
else if (*data_size) {
MHD_post_process(ms->post,data,*data_size);
@@ -1294,7 +1220,6 @@ proxy_bucket_post (void *cctx, struct MHD_Connection *conn, const
char *url,
}
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
}
return MHD_YES;
@@ -1369,7 +1294,6 @@ parts_callback (void *ctx, uint64_t pos, char *buf, size_t max)
if (!ms->gen_ctx) {
return -1;
}
- ms->cleanup |= CLEANUP_TMPL;
ms->gen_ctx->base = host;
len = tmpl_obj_header(ms->gen_ctx,ms->bucket,ms->key);
if (!len) {
@@ -1415,7 +1339,6 @@ parts_callback (void *ctx, uint64_t pos, char *buf, size_t max)
}
memcpy(buf,ms->gen_ctx->buf,len);
free(ms->gen_ctx);
- ms->cleanup &= ~CLEANUP_TMPL;
ms->gen_ctx = TMPL_CTX_DONE;
return len;
}
@@ -1429,7 +1352,6 @@ show_parts (struct MHD_Connection *conn, my_state *ms)
if (!ms->aquery) {
return MHD_HTTP_NOT_FOUND;
}
- ms->cleanup |= CLEANUP_AQUERY;
resp = MHD_create_response_from_callback(MHD_SIZE_UNKNOWN,
65536, parts_callback, ms, simple_closer);
@@ -1464,10 +1386,8 @@ proxy_object_post (void *cctx, struct MHD_Connection *conn, const
char *url,
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
g_str_hash,g_str_equal,NULL,NULL);
- ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
post_iterator,ms->dict);
- ms->cleanup |= CLEANUP_POST;
}
else if (*data_size) {
MHD_post_process(ms->post,data,*data_size);
@@ -1511,12 +1431,10 @@ proxy_object_post (void *cctx, struct MHD_Connection *conn, const
char *url,
MHD_NO,MHD_NO);
if (!resp) {
fprintf(stderr,"MHD_crfd failedn");
- free_ms(ms);
return MHD_NO;
}
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
}
}
@@ -1544,7 +1462,6 @@ prov_list_generator (void *ctx, uint64_t pos, char *buf, size_t
max)
if (!ms->gen_ctx) {
return -1;
}
- ms->cleanup |= CLEANUP_TMPL;
init_prov_iter(&ms->prov_iter);
len = tmpl_prov_header(ms->gen_ctx);
if (!len) {
@@ -1585,7 +1502,6 @@ prov_list_generator (void *ctx, uint64_t pos, char *buf, size_t
max)
}
memcpy(buf,ms->gen_ctx->buf,len);
free(ms->gen_ctx);
- ms->cleanup &= ~CLEANUP_TMPL;
ms->gen_ctx = TMPL_CTX_DONE;
return len;
}
@@ -1657,10 +1573,8 @@ proxy_update_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
g_str_hash,g_str_equal,NULL,NULL);
- ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
prov_iterator,ms->dict);
- ms->cleanup |= CLEANUP_POST;
}
else if (*data_size) {
MHD_post_process(ms->post,data,*data_size);
@@ -1681,12 +1595,10 @@ proxy_update_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
resp = MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
if (!resp) {
fprintf(stderr,"MHD_crfd failedn");
- free_ms(ms);
return MHD_NO;
}
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
}
return MHD_YES;
@@ -1813,7 +1725,6 @@ proxy_delete_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
struct MHD_Response *resp
= MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
if (!resp) {
- free_ms(ms);
return MHD_NO;
}
@@ -1829,19 +1740,13 @@ proxy_delete_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
DPRINTF("PROXY DELETE PROVIDER prov=%s rc=%dn", prov_name, rc);
if (prov) {
- /* Delete for real if no one is using it.
- Otherwise, just mark it as deleted. */
- if (g_atomic_int_get (&prov->refcnt) == 0)
- delete_provider (prov);
- else
- prov->deleted = 1;
+ prov->deleted = 1;
}
free (prov_name);
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
return MHD_YES;
}
@@ -1863,10 +1768,8 @@ proxy_add_prov (void *cctx, struct MHD_Connection *conn, const char
*url,
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
g_str_hash,g_str_equal,NULL,NULL);
- ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
prov_iterator,ms->dict);
- ms->cleanup |= CLEANUP_POST;
}
else if (*data_size) {
MHD_post_process(ms->post,data,*data_size);
@@ -1916,7 +1819,6 @@ proxy_add_prov (void *cctx, struct MHD_Connection *conn, const char
*url,
}
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
}
return MHD_YES;
@@ -1949,7 +1851,6 @@ proxy_create_bucket (void *cctx, struct MHD_Connection *conn, const
char *url,
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
- free_ms(ms);
return MHD_YES;
}
@@ -2077,7 +1978,6 @@ access_handler (void *cctx, struct MHD_Connection *conn, const char
*url,
if (!ms) {
return MHD_NO;
}
- ms->refcnt = 1;
utype = parse_url(url,ms);
@@ -2101,9 +2001,6 @@ access_handler (void *cctx, struct MHD_Connection *conn, const char
*url,
data,data_size,rctx);
}
- /* Don't need this after all. Free before the next check. */
- free_ms(ms);
-
if (!strcmp(method,"QUIT")) {
(void)sem_post((sem_t *)cctx);
return MHD_NO;
diff --git a/setup.c b/setup.c
index b3173ff..505c9cb 100644
--- a/setup.c
+++ b/setup.c
@@ -331,7 +331,6 @@ convert_provider (int i, provider_t *out)
out->token = NULL;
out->deleted = 0;
- out->refcnt = 0;
return 1;
}
@@ -595,19 +594,6 @@ find_provider (const char *name)
return p;
}
-void
-delete_provider (provider_t *prov)
-{
- // Remove from prov_hash, then free
-
- g_hash_table_destroy(prov->attrs);
- // FIXME: free other members, too?
-
- // FIXME: unchecked strdup
- char *name = strdup (prov->name);
- g_hash_table_remove(prov_hash, prov->name);
-}
-
const char *
get_provider_value (const provider_t *prov, const char *fname)
{
diff --git a/setup.h b/setup.h
index 54a4ca3..fb50944 100644
--- a/setup.h
+++ b/setup.h
@@ -27,7 +27,6 @@ typedef struct _provider {
const char *host;
int port;
int deleted;
- gint refcnt;
const char *username;
const char *password;
const char *path;
@@ -51,7 +50,6 @@ const char *auto_config (void);
int validate_provider (GHashTable *h);
provider_t *find_provider (const char *name);
int add_provider (GHashTable *h);
-void delete_provider (provider_t *prov);
provider_t *get_main_provider (void);
void set_main_provider (provider_t *prov);
diff --git a/state_defs.h b/state_defs.h
index 1443236..a35cd8d 100644
--- a/state_defs.h
+++ b/state_defs.h
@@ -44,8 +44,6 @@ typedef struct {
} backend_thunk_t;
typedef struct _my_state {
- volatile gint refcnt;
- int cleanup;
/* for everyone */
MHD_AccessHandlerCallback handler;
ms_state state;
@@ -90,6 +88,4 @@ typedef struct _my_state {
#define BACKEND_GET_SIZE 0x01 /* used in put_child_func */
-void free_ms (my_state *ms);
-
#endif
http://repo.or.cz/w/iwhd.git/commit/2b64c1ad809e9b657a7a52d8d49e2f3604f526fc
commit 2b64c1ad809e9b657a7a52d8d49e2f3604f526fc
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Dec 23 18:36:38 2010 +0100
garbage-collection fix-up
Do not instruct libraries to free things that they do not allocate,
since they would use the system "free" function.
* setup.c, rest.c: Do not tell g_hash_table_new_full to free anything.
* rest.c (proxy_get_attr): Do not tell MHD to free anything.
diff --git a/rest.c b/rest.c
index 3585020..059d7bf 100644
--- a/rest.c
+++ b/rest.c
@@ -316,7 +316,6 @@ proxy_get_data (void *cctx, struct MHD_Connection *conn, const char
*url,
MHD_destroy_response(resp);
return MHD_YES;
}
- free(my_etag);
ms->from_master = 0;
}
else {
@@ -384,7 +383,6 @@ static void
recheck_replication (my_state * ms, char *policy)
{
int rc;
- int free_it = FALSE;
char fixed[MAX_FIELD_LEN];
if (is_reserved(ms->key,reserved_name)) {
@@ -398,8 +396,6 @@ recheck_replication (my_state * ms, char *policy)
}
if (!policy) {
- /* If we get a policy here or below, we have to free it. */
- free_it = TRUE;
DPRINTF("fetching policy for %s/%sn",ms->bucket,ms->key);
rc = meta_get_value(ms->bucket,ms->key, "_policy", &policy);
}
@@ -418,9 +414,6 @@ recheck_replication (my_state * ms, char *policy)
*/
snprintf(fixed,sizeof(fixed),"%s/%s",ms->bucket,ms->key);
replicate(fixed,0,policy,ms);
- if (free_it) {
- free(policy);
- }
}
else {
DPRINTF(" could not find a policy anywhere!n");
@@ -554,7 +547,6 @@ proxy_put_data (void *cctx, struct MHD_Connection *conn, const char
*url,
}
if (etag) {
MHD_add_response_header(resp,"ETag",etag);
- free(etag);
}
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
@@ -583,7 +575,7 @@ proxy_get_attr (void *cctx, struct MHD_Connection *conn, const char
*url,
if (meta_get_value(ms->bucket,ms->key,ms->attr,&fixed) == 0) {
resp = MHD_create_response_from_data(strlen(fixed),fixed,
- MHD_YES,MHD_NO);
+ MHD_NO,MHD_NO);
rc = MHD_HTTP_OK;
}
else {
@@ -1195,7 +1187,7 @@ control_api_root (void *cctx, struct MHD_Connection *conn, const
char *url,
ms->state = MS_NORMAL;
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
- g_str_hash,g_str_equal,free,free);
+ g_str_hash,g_str_equal,NULL,NULL);
ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
post_iterator,ms->dict);
@@ -1263,7 +1255,7 @@ proxy_bucket_post (void *cctx, struct MHD_Connection *conn, const
char *url,
ms->state = MS_NORMAL;
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
- g_str_hash,g_str_equal,free,free);
+ g_str_hash,g_str_equal,NULL,NULL);
ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
post_iterator,ms->dict);
@@ -1471,7 +1463,7 @@ proxy_object_post (void *cctx, struct MHD_Connection *conn, const
char *url,
ms->state = MS_NORMAL;
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
- g_str_hash,g_str_equal,free,free);
+ g_str_hash,g_str_equal,NULL,NULL);
ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
post_iterator,ms->dict);
@@ -1664,7 +1656,7 @@ proxy_update_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
ms->state = MS_NORMAL;
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
- g_str_hash,g_str_equal,free,free);
+ g_str_hash,g_str_equal,NULL,NULL);
ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
prov_iterator,ms->dict);
@@ -1870,7 +1862,7 @@ proxy_add_prov (void *cctx, struct MHD_Connection *conn, const char
*url,
ms->state = MS_NORMAL;
ms->url = (char *)url;
ms->dict = g_hash_table_new_full(
- g_str_hash,g_str_equal,free,free);
+ g_str_hash,g_str_equal,NULL,NULL);
ms->cleanup |= CLEANUP_DICT;
ms->post = MHD_create_post_processor(conn,4096,
prov_iterator,ms->dict);
diff --git a/setup.c b/setup.c
index d1daa19..b3173ff 100644
--- a/setup.c
+++ b/setup.c
@@ -307,7 +307,7 @@ convert_provider (int i, provider_t *out)
out->func_tbl = &bad_func_tbl;
}
- out->attrs = g_hash_table_new_full(g_str_hash,g_str_equal,free,free);
+ out->attrs = g_hash_table_new_full(g_str_hash,g_str_equal,NULL,NULL);
iter = json_object_iter(server);
while (iter) {
key = json_object_iter_key(iter);
@@ -385,7 +385,7 @@ add_provider (GHashTable *h)
else
prov->func_tbl = &bad_func_tbl;
- prov->attrs = g_hash_table_new_full(g_str_hash,g_str_equal,free,free);
+ prov->attrs = g_hash_table_new_full(g_str_hash,g_str_equal,NULL,NULL);
// FIXME: can't the above fail?
GHashTableIter iter;
@@ -453,7 +453,7 @@ parse_config_inner (void)
/* Everything looks OK. */
printf("%u replication servers definedn",nservers-1);
- prov_hash = g_hash_table_new_full(g_str_hash,g_str_equal,free,free);
+ prov_hash = g_hash_table_new_full(g_str_hash,g_str_equal,NULL,NULL);
if (!prov_hash) {
error(0,0,"could not allocate provider hash");
goto err;
http://repo.or.cz/w/iwhd.git/commit/ae15a4eabca8853eb16bb4e9df6c235a1ce15b1a
commit ae15a4eabca8853eb16bb4e9df6c235a1ce15b1a
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Dec 23 18:17:23 2010 +0100
don't use xstrndup via base_name
* rest.c (url_to_provider_name): Rewrite not to use base_name, since
that function uses xstrndup, which exits on OOM.
diff --git a/rest.c b/rest.c
index 978ef89..3585020 100644
--- a/rest.c
+++ b/rest.c
@@ -1703,12 +1703,15 @@ proxy_update_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
static char *
url_to_provider_name (const char *url)
{
- char *prov_name = base_name (url);
- if (prov_name)
- strip_trailing_slashes (prov_name);
+ char *p = strdup (url);
+ if (p == NULL)
+ return NULL;
+
/* Ensure we handle trailing slashes (i.e., remove them). */
- assert (prov_name == NULL
- || (*prov_name && prov_name[strlen(prov_name)-1] != '/'));
+ strip_trailing_slashes (p);
+
+ char *prov_name = strdup (last_component (p));
+ free (p);
return prov_name;
}
http://repo.or.cz/w/iwhd.git/commit/ed0b229107cca6b51adfb1ffb6079a2a23546a75
commit ed0b229107cca6b51adfb1ffb6079a2a23546a75
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Dec 22 17:25:19 2010 +0100
use garbage collection
Add -lgc when linking.
* gc-wrap.h: New file, to map malloc, realloc, free,
etc. to GC'd equivalents.
* iwh.h: Include it.
* template.c: Include it.
* Makefile.am (iwhd_LDADD): Add -lgc and -lpthread.
* t/Makefile.am (parser_LDADD): Likewise.
* Makefile.am (iwhd_SOURCES): Add gc-wrap.h.
(TESTS): Move the simpler parser-test to precede all others.
* iwhd.spec.in (BuildRequires): Require gc-devel.
* qparser.y (free_value): Remove function.
* meta.cpp, replica.c: Remove all uses.
* query.h: Remove declaration.
* rest.c (main): Call GC_INIT.
* qparser.y (main) [PARSER_UNIT_TEST]: Likewise.
* mpipe.c: Include unistd.h here, ...
* mpipe.h: ...not here.
Don't include the following, either: fcntl.h, stdlib.h, string.h,
strings.h, sys/stat.h. They were not used, and got in the way
of gc-wrap's redefinitions.
diff --git a/Makefile.am b/Makefile.am
index 4360dd4..cbf2fc2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -40,6 +40,7 @@ iwhd_SOURCES = auto.c backend.c backend.h + gc-wrap.h
iwh.h meta.cpp meta.h @@ -94,6 +95,7 @@ rpm: dist iwhd.spec
iwhd_CPPFLAGS = $(HAIL_CFLAGS) -I$(top_srcdir)/lib
iwhd_LDADD = lib/libiwhd.a + -lgc -lpthread -lmongoclient
$(BOOST_SYSTEM_LIB) $(BOOST_THREAD_LIB) diff --git a/gc-wrap.h b/gc-wrap.h
new file mode 100644
index 0000000..70c4b9d
--- /dev/null
+++ b/gc-wrap.h
@@ -0,0 +1,35 @@
+#include <string.h>
+#define GC_THREADS
+#include "gc.h"
+
+#ifndef __cplusplus
+# define malloc(n) GC_MALLOC(n)
+# define calloc(m,n) GC_MALLOC((m)*(n))
+# define free(p) GC_FREE(p)
+# define realloc(p,n) GC_REALLOC((p),(n))
+#endif
+
+static inline char *
+my_strdup (char const *s)
+{
+ size_t len = strlen (s);
+ void *t = GC_MALLOC (len + 1);
+ if (t == NULL)
+ return NULL;
+ return (char *) memcpy (t, s, len + 1);
+}
+# undef strdup
+# define strdup(s) my_strdup(s)
+
+static inline char *
+my_strndup (char const *s, size_t n)
+{
+ size_t len = strnlen (s, n);
+ char *t = (char *) GC_MALLOC (len + 1);
+ if (t == NULL)
+ return NULL;
+ t[len] = '0';
+ return (char *) memcpy (t, s, len);
+}
+# undef strndup
+# define strndup(s, n) my_strndup(s, n)
diff --git a/iwh.h b/iwh.h
index c862273..b98e6ba 100644
--- a/iwh.h
+++ b/iwh.h
@@ -69,3 +69,5 @@ GLOBAL(const char *, me, "here");
#define AUTO_MONGOD_PORT 27018
int auto_start (int dbport);
+
+#include "gc-wrap.h"
diff --git a/iwhd.spec.in b/iwhd.spec.in
index 2b28b53..eae6086 100644
--- a/iwhd.spec.in
+++ b/iwhd.spec.in
@@ -17,6 +17,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u}
-n)
BuildRequires: boost-devel
BuildRequires: boost-filesystem
+BuildRequires: gc-devel
BuildRequires: glib2-devel
BuildRequires: hail-devel
BuildRequires: jansson-devel
diff --git a/meta.cpp b/meta.cpp
index b7ae903..59d4e53 100644
--- a/meta.cpp
+++ b/meta.cpp
@@ -440,9 +440,6 @@ RepoQuery::RepoQuery (const char *bucket, const char *key, const char
*qstr,
RepoQuery::~RepoQuery ()
{
cout << "in " << __func__ << endl;
- if (expr) {
- free_value(expr);
- }
delete curs;
}
diff --git a/mpipe.c b/mpipe.c
index 46b3ad2..8272168 100644
--- a/mpipe.c
+++ b/mpipe.c
@@ -15,6 +15,7 @@
#include <config.h>
#include <assert.h>
+#include <unistd.h>
#include "iwh.h"
#include "mpipe.h"
diff --git a/mpipe.h b/mpipe.h
index 9d0f795..cf0ec72 100644
--- a/mpipe.h
+++ b/mpipe.h
@@ -16,17 +16,11 @@
#if !defined(_MPIPE_H)
#define _MPIPE_H
-#include <fcntl.h>
#include <poll.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdint.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <unistd.h>
-#include <sys/stat.h>
/*
* This is an in-memory "pipe" construct with a twist: it lets you have
diff --git a/qparser.y b/qparser.y
index 64f025a..8ef7fe0 100644
--- a/qparser.y
+++ b/qparser.y
@@ -387,41 +387,6 @@ print_value (const value_t *v)
_print_value(v,0);
}
-void
-free_value (value_t *v)
-{
- if (v == NULL || v == &invalid) {
- return;
- }
-
- free((void *)v->resolved);
-
- switch (v->type) {
- case T_STRING:
- case T_OFIELD:
- case T_SFIELD:
- case T_ID:
- free(v->as_str);
- free(v);
- break;
- case T_LINK:
- free_value(v->as_tree.left);
- free(v->as_tree.right);
- free(v);
- break;
- case T_COMP:
- case T_AND:
- case T_OR:
- free_value(v->as_tree.right);
- /* Fall through. */
- case T_NOT:
- free_value(v->as_tree.left);
- /* Fall through. */
- default:
- free(v);
- }
-}
-
#include "qlexer.c"
value_t *
@@ -433,8 +398,6 @@ parse (const char *text)
YY_BUFFER_STATE buf = yy_scan_string (text, scanner);
value_t *result = NULL;
value_t *r = yyparse (scanner, &result) == 0 ? result : NULL;
- if (r == NULL)
- free_value (result);
yy_delete_buffer (buf, scanner);
yylex_destroy (scanner);
return r;
@@ -644,6 +607,7 @@ main (int argc, char **argv)
{
int fail = 0;
unsigned int i;
+ GC_INIT ();
for (i = 1; i < argc; ++i)
{
value_t *expr = parse (argv[i]);
@@ -651,7 +615,7 @@ main (int argc, char **argv)
{
printf ("could not parse '%s'n", argv[i]);
fail = 1;
- goto next;
+ continue;
}
print_value (expr);
@@ -660,12 +624,9 @@ main (int argc, char **argv)
if (str)
{
printf ("s= %sn", str);
- goto next;
+ continue;
}
printf ("d= %dn", eval (expr, &unit_oget, &unit_sget));
-
- next:
- free_value (expr);
}
return fail;
diff --git a/query.h b/query.h
index 523dd91..de42d80 100644
--- a/query.h
+++ b/query.h
@@ -69,9 +69,9 @@ typedef struct {
#define CALL_GETTER(g,x) g->func(g->ctx,x)
/*
- * In the normal case a caller would invoke parse once, eval multiple times,
- * and free_value once. print_value is just for debugging/testing.
- * TBD: make parse reentrant (eval already is, free_value doesn't need to be.
+ * In the normal case a caller would invoke parse once and eval multiple times.
+ * print_value is just for debugging/testing.
+ * TBD: make parse reentrant (eval already is).
* Unfortunately, a quick scan of generated code and information on the web
* seems to indicate that even a "reentrant" bison parser only encapsulates
* user state and still relies quite a bit on internal globals. That might
@@ -79,7 +79,6 @@ typedef struct {
*/
int eval (const value_t *expr,
const getter_t *oget, const getter_t *sget);
-void free_value (value_t *);
void print_value (const value_t *);
value_t *parse (const char *text);
diff --git a/replica.c b/replica.c
index 301c8d3..1910747 100644
--- a/replica.c
+++ b/replica.c
@@ -354,9 +354,6 @@ replicate (const char *url, size_t size, const char *policy, my_state
*ms)
sem_post(&queue_sema);
}
- if (expr) {
- free_value(expr);
- }
free(url2);
}
diff --git a/rest.c b/rest.c
index 972c2fc..978ef89 100644
--- a/rest.c
+++ b/rest.c
@@ -2193,6 +2193,7 @@ main (int argc, char **argv)
set_program_name (argv[0]);
atexit (close_stdout);
+ GC_INIT ();
for (;;) switch (getopt_long(argc,argv,"ac:d:m:p:v",my_options,NULL)) {
case 'a':
diff --git a/t/Makefile.am b/t/Makefile.am
index 87fe3e4..0b3d100 100644
--- a/t/Makefile.am
+++ b/t/Makefile.am
@@ -15,9 +15,9 @@
# along with this program. If not, see <
http://www.gnu.org/licenses/>.
TESTS = + parser-test basic replication - parser-test
auto
EXTRA_DIST = @@ -31,7 +31,7 @@ BUILT_SOURCES =
BUILT_SOURCES += parser.c
MAINTAINERCLEANFILES = $(BUILT_SOURCES)
parser_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/lib
-parser_LDADD = -L../lib -liwhd
+parser_LDADD = -L../lib -liwhd -lgc -lpthread
parser.c: Makefile.am
rm -f $@-t $@
diff --git a/template.c b/template.c
index 2d49e2c..1b78bf4 100644
--- a/template.c
+++ b/template.c
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <string.h>
#include "template.h"
+#include "gc-wrap.h"
static const char xml_root_header[] = " <api service="%s"
version="%s">
http://repo.or.cz/w/iwhd.git/commit/2d99e43fee5f7af7f6ec6fd238ee900f9fb103aa
commit 2d99e43fee5f7af7f6ec6fd238ee900f9fb103aa
Author: Jim Meyering <meyering(a)redhat.com>
Date: Sat Dec 18 11:08:25 2010 +0100
maint: rename file-scoped global s/main_prov/g_main_prov/, and...
* setup.c (g_main_prov): Rename from main_prov, to avoid confusion
between this file-scoped global and the locals of the same name
in other compilation units.
(g_master_prov): Rename from master_prov, for consistency.
Though this one is truly global...
* setup.h (g_master_prov): Update here,...
* rest.c (g_master_prov): ...and here.
diff --git a/rest.c b/rest.c
index b58f1bc..972c2fc 100644
--- a/rest.c
+++ b/rest.c
@@ -341,7 +341,7 @@ proxy_get_data (void *cctx, struct MHD_Connection *conn, const char
*url,
}
provider_t *main_prov = get_main_provider();
ms->thunk.parent = ms;
- ms->thunk.prov = ms->from_master ? master_prov : main_prov;
+ ms->thunk.prov = ms->from_master ? g_master_prov : main_prov;
pthread_create(&ms->backend_th,NULL,
ms->thunk.prov->func_tbl->get_child_func,&ms->thunk);
/* TBD: check return value */
diff --git a/setup.c b/setup.c
index 6ae5f01..d1daa19 100644
--- a/setup.c
+++ b/setup.c
@@ -69,19 +69,19 @@ extern backend_func_tbl fs_func_tbl;
static json_t *config = NULL;
static GHashTable *prov_hash = NULL;
-static provider_t *main_prov = NULL;
-provider_t *master_prov = NULL;
+static provider_t *g_main_prov = NULL;
+provider_t *g_master_prov = NULL;
provider_t *
get_main_provider (void)
{
- return main_prov;
+ return g_main_prov;
}
void
set_main_provider (provider_t *prov)
{
- main_prov = prov;
+ g_main_prov = prov;
}
int
@@ -482,7 +482,7 @@ parse_config_inner (void)
}
g_hash_table_insert(prov_hash,(char *)new_key,new_prov);
if (!i) {
- main_prov = new_prov;
+ g_main_prov = new_prov;
primary = new_prov->name;
}
new_prov->func_tbl->init_func(new_prov);
@@ -511,10 +511,10 @@ parse_config (char *cfg_file)
* TBD: initialize this in a separate module-init function, passing
* in master_host and master_port instead of using globals.
*/
- if (!master_prov) {
- master_prov = malloc(sizeof(*master_prov));
- if (master_prov) {
- master_prov->func_tbl = &curl_func_tbl;
+ if (!g_master_prov) {
+ g_master_prov = malloc(sizeof(*g_master_prov));
+ if (g_master_prov) {
+ g_master_prov->func_tbl = &curl_func_tbl;
}
}
diff --git a/setup.h b/setup.h
index 0bfbb81..54a4ca3 100644
--- a/setup.h
+++ b/setup.h
@@ -36,7 +36,7 @@ typedef struct _provider {
char *token;
} provider_t;
-provider_t *master_prov;
+provider_t *g_master_prov;
const char *parse_config (char *);
provider_t *get_provider (const char *name);
http://repo.or.cz/w/iwhd.git/commit/9bc8fc19e7d70de1fe8968bf2b844ee9c15b3574
commit 9bc8fc19e7d70de1fe8968bf2b844ee9c15b3574
Author: Jim Meyering <meyering(a)redhat.com>
Date: Sat Dec 18 10:47:58 2010 +0100
rename a URL API component: s/_set_primary/_primary/
Suggested by Jeff Darcy.
diff --git a/rest.c b/rest.c
index be4a888..b58f1bc 100644
--- a/rest.c
+++ b/rest.c
@@ -1762,7 +1762,7 @@ proxy_set_primary (void *cctx, struct MHD_Connection *conn, const
char *url,
char *name = NULL;
unsigned int rc = MHD_HTTP_BAD_REQUEST;
- /* URL is guaranteed to be of the form "/_providers/NAME/_set_primary"
+ /* URL is guaranteed to be of the form "/_providers/NAME/_primary"
Extract NAME: */
bool valid = memcmp (url, "/_providers/", strlen("/_providers/")) ==
0;
if (!valid) {
@@ -2055,7 +2055,7 @@ parse_url (const char *url, my_state *ms)
eindex = URL_PROVIDER;
else if (eindex == URL_ATTR
&& !strcmp (parts[URL_BUCKET], "_providers")
- && !strcmp (parts[URL_ATTR], "_set_primary"))
+ && !strcmp (parts[URL_ATTR], "_primary"))
eindex = URL_PROVIDER_SET_PRIMARY;
DPRINTF("parse_url: %d: %s %s %s", eindex, parts[URL_BUCKET],
diff --git a/t/basic b/t/basic
index 436f123..a2f91ca 100644
--- a/t/basic
+++ b/t/basic
@@ -366,7 +366,7 @@ curl
http://localhost:$port/_primary > p || fail=1
grep _primary p && { warn_ add-provider/reserved-name not rejected; fail=1; }
# Move the "primary" attribute to a different provider.
-curl -X PUT $p1_url/_set_primary > p || fail=1
+curl -X PUT $p1_url/_primary > p || fail=1
test -s p && fail=1
new_primary=$(curl
http://localhost:$port/_providers/_primary) || fail=1
test $new_primary = PROVIDER-1 || fail=1
@@ -375,7 +375,7 @@ test $new_primary = PROVIDER-1 || fail=1
# FIXME: if I don't restore, the following headless test makes iwhd segfault.
# Investigate that.
p1_url=http://localhost:$port/_providers/primary
-curl -X PUT $p1_url/_set_primary > p || fail=1
+curl -X PUT $p1_url/_primary > p || fail=1
http://repo.or.cz/w/iwhd.git/commit/e8699f536bb5cd49f8e20db1615221263938de07
commit e8699f536bb5cd49f8e20db1615221263938de07
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri Dec 17 17:07:47 2010 +0100
new interface: curl -X PUT
http://_providers/PROVIDER/_set_primary
* rest.c: Include <errno.h>.
(proxy_set_primary): New function.
(parse_url): Handle new type: URL_PROVIDER_SET_PRIMARY.
* setup.c (set_main_provider): New function.
* setup.h (set_main_provider): Declare it.
* t/basic: Exercise the new functionality.
diff --git a/rest.c b/rest.c
index cc0a99b..be4a888 100644
--- a/rest.c
+++ b/rest.c
@@ -28,6 +28,7 @@
#include <unistd.h>
#include <sys/stat.h>
#include <assert.h>
+#include <errno.h>
#include <microhttpd.h>
#include <hstor.h> /* only for ARRAY_SIZE at this point */
@@ -58,7 +59,7 @@
typedef enum {
URL_ROOT=0, URL_BUCKET, URL_OBJECT, URL_ATTR, URL_INVAL,
- URL_QUERY, URL_PROVLIST, URL_PROVIDER
+ URL_QUERY, URL_PROVLIST, URL_PROVIDER, URL_PROVIDER_SET_PRIMARY
} url_type;
typedef struct {
@@ -1746,6 +1747,62 @@ proxy_primary_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
}
static int
+proxy_set_primary (void *cctx, struct MHD_Connection *conn, const char *url,
+ const char *method, const char *version, const char *data,
+ size_t *data_size, void **rctx)
+{
+ (void)cctx;
+ (void)method;
+ (void)version;
+ (void)data;
+
+ DPRINTF("PROXY SET PRIMARY PROVIDER (%s)n", url);
+
+ my_state *ms = *rctx;
+ char *name = NULL;
+ unsigned int rc = MHD_HTTP_BAD_REQUEST;
+
+ /* URL is guaranteed to be of the form "/_providers/NAME/_set_primary"
+ Extract NAME: */
+ bool valid = memcmp (url, "/_providers/", strlen("/_providers/")) ==
0;
+ if (!valid) {
+ error (0, 0, "invalid request: %s", url);
+ goto bad_set;
+ }
+ const char *start = url + strlen("/_providers/");
+ const char *slash = strchr (start, '/');
+ if (slash == NULL) {
+ error (0, 0, "invalid request: %s", url);
+ goto bad_set;
+ }
+ name = strndup (start, slash - start);
+ if (name == NULL) {
+ error (0, errno, "failed to extract provider name: %s", url);
+ goto bad_set;
+ }
+
+ /* If it's not a provider name, you lose. */
+ provider_t *prov = find_provider (name);
+ if (prov) {
+ rc = MHD_HTTP_OK;
+ set_main_provider (prov);
+ }
+
+ bad_set:
+ free (name);
+
+ struct MHD_Response *resp;
+ resp = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO);
+ if (!resp) {
+ return MHD_NO;
+ }
+ MHD_queue_response(conn,rc,resp);
+ MHD_destroy_response(resp);
+
+ return MHD_YES;
+}
+
+static int
proxy_delete_prov (void *cctx, struct MHD_Connection *conn, const char *url,
const char *method, const char *version, const char *data,
size_t *data_size, void **rctx)
@@ -1938,6 +1995,8 @@ static const rule my_rules[] = {
"POST", URL_PROVIDER, proxy_add_prov },
{ /* delete a provider */
"DELETE", URL_PROVIDER, proxy_delete_prov },
+ { /* set the primary provider */
+ "PUT", URL_PROVIDER_SET_PRIMARY, proxy_set_primary },
{ NULL, 0, NULL }
};
@@ -1994,6 +2053,10 @@ parse_url (const char *url, my_state *ms)
if (eindex == URL_OBJECT
&& !strcmp (parts[URL_BUCKET], "_providers"))
eindex = URL_PROVIDER;
+ else if (eindex == URL_ATTR
+ && !strcmp (parts[URL_BUCKET], "_providers")
+ && !strcmp (parts[URL_ATTR], "_set_primary"))
+ eindex = URL_PROVIDER_SET_PRIMARY;
DPRINTF("parse_url: %d: %s %s %s", eindex, parts[URL_BUCKET],
parts[URL_OBJECT], parts[URL_ATTR]);
diff --git a/setup.c b/setup.c
index f613f24..6ae5f01 100644
--- a/setup.c
+++ b/setup.c
@@ -78,6 +78,12 @@ get_main_provider (void)
return main_prov;
}
+void
+set_main_provider (provider_t *prov)
+{
+ main_prov = prov;
+}
+
int
validate_provider (GHashTable *h)
{
diff --git a/setup.h b/setup.h
index ecdef5f..0bfbb81 100644
--- a/setup.h
+++ b/setup.h
@@ -53,5 +53,6 @@ provider_t *find_provider (const char *name);
int add_provider (GHashTable *h);
void delete_provider (provider_t *prov);
provider_t *get_main_provider (void);
+void set_main_provider (provider_t *prov);
#endif
diff --git a/t/basic b/t/basic
index 59e2608..436f123 100644
--- a/t/basic
+++ b/t/basic
@@ -365,6 +365,18 @@ curl -dtype=http -dhost=localhost -dport=9091 $p_reserved_url ||
fail=1
curl
http://localhost:$port/_primary > p || fail=1
grep _primary p && { warn_ add-provider/reserved-name not rejected; fail=1; }
+# Move the "primary" attribute to a different provider.
+curl -X PUT $p1_url/_set_primary > p || fail=1
+test -s p && fail=1
+new_primary=$(curl
http://localhost:$port/_providers/_primary) || fail=1
+test $new_primary = PROVIDER-1 || fail=1
+
+# Restore the primary attribute to the original.
+# FIXME: if I don't restore, the following headless test makes iwhd segfault.
+# Investigate that.
+p1_url=http://localhost:$port/_providers/primary
+curl -X PUT $p1_url/_set_primary > p || fail=1
+
# Test "headless" operation (no access to metadata DB).
http://repo.or.cz/w/iwhd.git/commit/55be76211cca12e07a644809272649176f336f0e
commit 55be76211cca12e07a644809272649176f336f0e
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri Dec 17 15:37:14 2010 +0100
get primary provider name via
http://host:$port/_providers/_primary
Get a URL of the form http://.../_providers/_primary
to obtain the name of the primary provider.
* rest.c (proxy_primary_prov): Implement it.
(proxy_add_prov): Prohibit addition of a provider
with the reserved name, "_primary".
* t/basic: Exercise the new functionality.
diff --git a/rest.c b/rest.c
index a56f2d3..cc0a99b 100644
--- a/rest.c
+++ b/rest.c
@@ -1712,6 +1712,40 @@ url_to_provider_name (const char *url)
}
static int
+proxy_primary_prov (void *cctx, struct MHD_Connection *conn, const char *url,
+ const char *method, const char *version, const char *data,
+ size_t *data_size, void **rctx)
+{
+ (void)cctx;
+ (void)method;
+ (void)version;
+ (void)data;
+
+ DPRINTF("PROXY GET PRIMARY PROVIDER (%s)n", url);
+
+ my_state *ms = *rctx;
+
+ // "/_providers/_primary" is the only one we accept for now.
+ bool valid = strcmp (url, "/_providers/_primary") == 0;
+ unsigned int rc = (valid ? MHD_HTTP_OK : MHD_HTTP_BAD_REQUEST);
+ if (!valid)
+ error (0, 0, "invalid request: %s", url);
+
+ const char *name = get_main_provider()->name;
+ struct MHD_Response *resp;
+ resp = MHD_create_response_from_data(valid ? strlen (name) : 0,
+ valid ? (void *) name : NULL,
+ MHD_NO, MHD_NO);
+ if (!resp) {
+ return MHD_NO;
+ }
+ MHD_queue_response(conn,rc,resp);
+ MHD_destroy_response(resp);
+
+ return MHD_YES;
+}
+
+static int
proxy_delete_prov (void *cctx, struct MHD_Connection *conn, const char *url,
const char *method, const char *version, const char *data,
size_t *data_size, void **rctx)
@@ -1798,6 +1832,16 @@ proxy_add_prov (void *cctx, struct MHD_Connection *conn, const char
*url,
name);
goto add_fail;
}
+
+ // another reserved word: provider name
+ // FIXME: don't hard-code it here
+ if (strcmp (prov_name, "_primary") == 0) {
+ fprintf(stderr,
+ "add_provider: %s is a reserved namen",
+ prov_name);
+ goto add_fail;
+ }
+
// FIXME: unchecked strdup
g_hash_table_insert(ms->dict,strdup("name"),prov_name);
@@ -1888,6 +1932,8 @@ static const rule my_rules[] = {
"GET", URL_PROVLIST, proxy_list_provs },
{ /* update a provider */
"POST", URL_PROVLIST, proxy_update_prov },
+ { /* get the primary provider */
+ "GET", URL_PROVIDER, proxy_primary_prov },
{ /* create a provider */
"POST", URL_PROVIDER, proxy_add_prov },
{ /* delete a provider */
diff --git a/t/basic b/t/basic
index 19eda9b..59e2608 100644
--- a/t/basic
+++ b/t/basic
@@ -350,6 +350,22 @@ curl -f -X DELETE
http://localhost:$port/_providers/no-such 2> p
test $? = 22 || fail=1
grep ' 404$' p || fail=1
+# Get the name of the current primary provider.
+curl
http://localhost:$port/_providers/_primary > p || fail=1
+test "$(cat p)" = primary || fail=1
+
+# Trying to GET with anything other than "_primary" returns the empty string.
+curl
http://localhost:$port/_providers/anything > p 2>/dev/null || fail=1
+test -s p && fail=1
+
+# Try to add a provider with the reserved name. It must fail.
+p_reserved_url=http://localhost:$port/_providers/_primary
+curl -dtype=http -dhost=localhost -dport=9091 $p_reserved_url || fail=1
+# Ensure it was not added.
+curl
http://localhost:$port/_primary > p || fail=1
+grep _primary p && { warn_ add-provider/reserved-name not rejected; fail=1; }
+
+
# Test "headless" operation (no access to metadata DB).
kill -9 $mongo_pid
http://repo.or.cz/w/iwhd.git/commit/2143b86e49ed10a3f59b08bff562f1a804d8f4d4
commit 2143b86e49ed10a3f59b08bff562f1a804d8f4d4
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Dec 16 18:27:10 2010 +0100
tests: clean up provider-deletion test
diff --git a/t/basic b/t/basic
index 0d394c7..19eda9b 100644
--- a/t/basic
+++ b/t/basic
@@ -345,13 +345,11 @@ curl
http://localhost:$port/_providers > p || fail=1
grep PROVIDER-2 p && { warn_ $ME_: provider deletion failed; fail=1; }
# Delete a non-existent provider.
-curl -f -X DELETE
http://localhost:$port/_providers/no-such
+curl -f -X DELETE
http://localhost:$port/_providers/no-such 2> p
+# ensure it fails; expect exit-22 and http: 404
test $? = 22 || fail=1
-# FIXME ensure it fails
-cat p
+grep ' 404$' p || fail=1
-curl
http://localhost:$port/_providers > p || fail=1
-cat p
# Test "headless" operation (no access to metadata DB).
kill -9 $mongo_pid
http://repo.or.cz/w/iwhd.git/commit/76d355f00798546cdc34079f3346547921c47185
commit 76d355f00798546cdc34079f3346547921c47185
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Dec 15 12:45:28 2010 +0100
use new function, get_main_provider, rather than global "main_prov"
* setup.c (get_main_provider): New function.
(main_prov): Declare static.
* setup.h (main_prov): Remove global decl.
(get_main_provider): Declare.
* rest.c, replica.c: Update all uses of "main_prov".
diff --git a/replica.c b/replica.c
index f0b4b51..301c8d3 100644
--- a/replica.c
+++ b/replica.c
@@ -73,7 +73,7 @@ proxy_repl_prod (void *ctx)
void *result;
thunk.parent = item->ms;
- thunk.prov = main_prov;
+ thunk.prov = get_main_provider();
result = thunk.prov->func_tbl->get_child_func(&thunk);
return result;
diff --git a/rest.c b/rest.c
index f7ece46..a56f2d3 100644
--- a/rest.c
+++ b/rest.c
@@ -338,6 +338,7 @@ proxy_get_data (void *cctx, struct MHD_Connection *conn, const char
*url,
if (!pp) {
return MHD_NO;
}
+ provider_t *main_prov = get_main_provider();
ms->thunk.parent = ms;
ms->thunk.prov = ms->from_master ? master_prov : main_prov;
pthread_create(&ms->backend_th,NULL,
@@ -468,6 +469,7 @@ proxy_put_data (void *cctx, struct MHD_Connection *conn, const char
*url,
if (!pp) {
return MHD_NO;
}
+ provider_t *main_prov = get_main_provider();
pp->prov = main_prov;
ms->be_flags = BACKEND_GET_SIZE;
pthread_create(&ms->backend_th,NULL,
@@ -913,6 +915,7 @@ proxy_delete (void *cctx, struct MHD_Connection *conn, const char
*url,
DPRINTF("PROXY DELETE %sn",url);
+ provider_t *main_prov = get_main_provider();
ms->thunk.parent = ms;
ms->thunk.prov = main_prov;
rc = ms->thunk.prov->func_tbl->delete_func(main_prov,
@@ -1145,6 +1148,7 @@ create_bucket (char *name, my_state *ms)
return MHD_HTTP_BAD_REQUEST;
}
+ provider_t *main_prov = get_main_provider();
rc = main_prov->func_tbl->bcreate_func(main_prov,name);
if (rc == MHD_HTTP_OK) {
if (meta_set_value(name,"_default", "_policy","0") != 0)
{
@@ -1730,8 +1734,8 @@ proxy_delete_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
char *prov_name = url_to_provider_name (url);
provider_t *prov = find_provider (prov_name);
- // don't allow removal of current main_prov.
- if (prov == main_prov)
+ // don't allow removal of current main provider.
+ if (prov == get_main_provider())
prov = NULL;
int rc = prov ? MHD_HTTP_OK : MHD_HTTP_NOT_FOUND;
@@ -2156,6 +2160,7 @@ args_done:
sem_init(&the_sem,0,0);
if (verbose) {
+ provider_t *main_prov = get_main_provider();
printf("primary store type is %sn",main_prov->type);
if (master_host) {
printf("operating as slave to %s:%un",
diff --git a/setup.c b/setup.c
index dc494af..f613f24 100644
--- a/setup.c
+++ b/setup.c
@@ -69,9 +69,15 @@ extern backend_func_tbl fs_func_tbl;
static json_t *config = NULL;
static GHashTable *prov_hash = NULL;
-provider_t *main_prov = NULL;
+static provider_t *main_prov = NULL;
provider_t *master_prov = NULL;
+provider_t *
+get_main_provider (void)
+{
+ return main_prov;
+}
+
int
validate_provider (GHashTable *h)
{
diff --git a/setup.h b/setup.h
index dc89a74..ecdef5f 100644
--- a/setup.h
+++ b/setup.h
@@ -36,7 +36,6 @@ typedef struct _provider {
char *token;
} provider_t;
-provider_t *main_prov;
provider_t *master_prov;
const char *parse_config (char *);
@@ -53,5 +52,6 @@ int validate_provider (GHashTable *h);
provider_t *find_provider (const char *name);
int add_provider (GHashTable *h);
void delete_provider (provider_t *prov);
+provider_t *get_main_provider (void);
#endif
http://repo.or.cz/w/iwhd.git/commit/4f53c5ae1af0508fe90f2539772e247560836f73
commit 4f53c5ae1af0508fe90f2539772e247560836f73
Author: Jim Meyering <meyering(a)redhat.com>
Date: Sat Dec 11 15:58:18 2010 +0100
reject an attempt to add a provider with "name" parameter
The "name" is specified as part of the URL, not via a parameter.
* rest.c (proxy_add_prov): Handle undesired "name" parameter properly.
* t/basic: Exercise the above.
diff --git a/rest.c b/rest.c
index 4797438..f7ece46 100644
--- a/rest.c
+++ b/rest.c
@@ -1792,8 +1792,7 @@ proxy_add_prov (void *cctx, struct MHD_Connection *conn, const char
*url,
fprintf(stderr,
"add_provider: do not specify name: name=%sn",
name);
- return MHD_NO;
- // FIXME: be careful that this does not leak "ms"
+ goto add_fail;
}
// FIXME: unchecked strdup
g_hash_table_insert(ms->dict,strdup("name"),prov_name);
@@ -1808,6 +1807,8 @@ proxy_add_prov (void *cctx, struct MHD_Connection *conn, const char
*url,
else {
DPRINTF("invalid providern");
}
+
+ add_fail:
resp = MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
if (!resp) {
fprintf(stderr,"MHD_crfd failedn");
diff --git a/t/basic b/t/basic
index fc42ac4..0d394c7 100644
--- a/t/basic
+++ b/t/basic
@@ -331,6 +331,13 @@ curl -dtype=http -dhost=localhost -dport=9091 $p2_url || fail=1
curl
http://localhost:$port/_providers > p || fail=1
grep PROVIDER-2 p || fail=1
+# Add provider using a "name" parameter (not permitted):
+p3_url=http://localhost:$port/_providers/PROVIDER-3
+curl -dtype=http -dname=X -dhost=localhost -dport=9091 $p3_url || fail=1
+# Ensure it was not added.
+curl
http://localhost:$port/_providers > p || fail=1
+grep PROVIDER-3 p && { warn_ add-provider-w/name-param not rejected; fail=1; }
+
# Delete a provider.
curl -f -X DELETE $p2_url 2> p || fail=1
# Ensure it was deleted.
http://repo.or.cz/w/iwhd.git/commit/042463398c4b70c98a4c4890addae0a21fdc97c4
commit 042463398c4b70c98a4c4890addae0a21fdc97c4
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri Dec 10 21:11:27 2010 +0100
add provider ref-counting; FIXME: partial impl. (i.e., no incr)
delete_provider: New function.
diff --git a/rest.c b/rest.c
index f156862..4797438 100644
--- a/rest.c
+++ b/rest.c
@@ -1728,7 +1728,6 @@ proxy_delete_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
}
char *prov_name = url_to_provider_name (url);
- DPRINTF("PROXY DELETE PROVIDER prov=%sn", prov_name);
provider_t *prov = find_provider (prov_name);
// don't allow removal of current main_prov.
@@ -1736,10 +1735,17 @@ proxy_delete_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
prov = NULL;
int rc = prov ? MHD_HTTP_OK : MHD_HTTP_NOT_FOUND;
- if (prov)
- prov->deleted = 1;
- error (0, 0, "DELETE PROV: rc=%d", rc);
+ DPRINTF("PROXY DELETE PROVIDER prov=%s rc=%dn", prov_name, rc);
+
+ if (prov) {
+ /* Delete for real if no one is using it.
+ Otherwise, just mark it as deleted. */
+ if (g_atomic_int_get (&prov->refcnt) == 0)
+ delete_provider (prov);
+ else
+ prov->deleted = 1;
+ }
free (prov_name);
MHD_queue_response(conn,rc,resp);
diff --git a/setup.c b/setup.c
index 86061d1..dc494af 100644
--- a/setup.c
+++ b/setup.c
@@ -319,6 +319,7 @@ convert_provider (int i, provider_t *out)
out->token = NULL;
out->deleted = 0;
+ out->refcnt = 0;
return 1;
}
@@ -582,6 +583,19 @@ find_provider (const char *name)
return p;
}
+void
+delete_provider (provider_t *prov)
+{
+ // Remove from prov_hash, then free
+
+ g_hash_table_destroy(prov->attrs);
+ // FIXME: free other members, too?
+
+ // FIXME: unchecked strdup
+ char *name = strdup (prov->name);
+ g_hash_table_remove(prov_hash, prov->name);
+}
+
const char *
get_provider_value (const provider_t *prov, const char *fname)
{
diff --git a/setup.h b/setup.h
index 11d2207..dc89a74 100644
--- a/setup.h
+++ b/setup.h
@@ -26,7 +26,8 @@ typedef struct _provider {
const char *type;
const char *host;
int port;
- int deleted;
+ int deleted;
+ gint refcnt;
const char *username;
const char *password;
const char *path;
@@ -51,5 +52,6 @@ const char *auto_config (void);
int validate_provider (GHashTable *h);
provider_t *find_provider (const char *name);
int add_provider (GHashTable *h);
+void delete_provider (provider_t *prov);
#endif
http://repo.or.cz/w/iwhd.git/commit/e87a2a25917713f20e0543caac8ab9cef0435077
commit e87a2a25917713f20e0543caac8ab9cef0435077
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Nov 15 17:50:53 2010 +0100
allow dynamic addition/deletion of providers
* setup.h (struct _provider) [deleted]: New member.
* setup.c (validate_provider): New function.
(json_validate_server): Renamed from validate_server.
(convert_provider): Initialize new "deleted" member.
(add_provider, find_provider): New functions.
Declare new functions.
* rest.c (prov_list_generator): Don't list a provider that
is marked as deleted.
(url_to_provider_name): New function.
(proxy_delete_prov, proxy_add_prov): New functions.
(my_rules): Add corresponding entries in this table.
* t/basic: Add minimal tests of new functionality.
diff --git a/rest.c b/rest.c
index ea8b289..f156862 100644
--- a/rest.c
+++ b/rest.c
@@ -34,6 +34,7 @@
#include <curl/curl.h>
#include <glib.h>
+#include "dirname.h"
#include "iwh.h"
#include "closeout.h"
#include "progname.h"
@@ -57,7 +58,7 @@
typedef enum {
URL_ROOT=0, URL_BUCKET, URL_OBJECT, URL_ATTR, URL_INVAL,
- URL_QUERY, URL_PROVLIST
+ URL_QUERY, URL_PROVLIST, URL_PROVIDER
} url_type;
typedef struct {
@@ -931,6 +932,7 @@ proxy_delete (void *cctx, struct MHD_Connection *conn, const char
*url,
free_ms(ms);
return MHD_NO;
}
+ error (0, 0, "DELETE BUCKET: rc=%d", rc);
MHD_queue_response(conn,rc,resp);
MHD_destroy_response(resp);
@@ -1458,7 +1460,7 @@ proxy_object_post (void *cctx, struct MHD_Connection *conn, const
char *url,
(void)method;
(void)version;
- DPRINTF("PROXY POST (%s, %zu)n",url,*data_size);
+ DPRINTF("PROXY POST obj (%s, %zu)n",url,*data_size);
if (ms->state == MS_NEW) {
ms->state = MS_NORMAL;
@@ -1563,6 +1565,8 @@ prov_list_generator (void *ctx, uint64_t pos, char *buf, size_t
max)
}
if (g_hash_table_iter_next(&ms->prov_iter,&key,(gpointer *)&prov)) {
+ if (prov->deleted)
+ return 0;
len = tmpl_prov_entry(ms->gen_ctx,prov->name,prov->type,
prov->host, prov->port, prov->username, prov->password);
if (!len) {
@@ -1691,6 +1695,126 @@ proxy_update_prov (void *cctx, struct MHD_Connection *conn, const
char *url,
return MHD_YES;
}
+static char *
+url_to_provider_name (const char *url)
+{
+ char *prov_name = base_name (url);
+ if (prov_name)
+ strip_trailing_slashes (prov_name);
+ /* Ensure we handle trailing slashes (i.e., remove them). */
+ assert (prov_name == NULL
+ || (*prov_name && prov_name[strlen(prov_name)-1] != '/'));
+ return prov_name;
+}
+
+static int
+proxy_delete_prov (void *cctx, struct MHD_Connection *conn, const char *url,
+ const char *method, const char *version, const char *data,
+ size_t *data_size, void **rctx)
+{
+ DPRINTF("PROXY DELETE PROVIDER %sn",url);
+ (void)cctx;
+ (void)method;
+ (void)version;
+ (void)data;
+ (void)data_size;
+
+ my_state *ms = *rctx;
+ struct MHD_Response *resp
+ = MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
+ if (!resp) {
+ free_ms(ms);
+ return MHD_NO;
+ }
+
+ char *prov_name = url_to_provider_name (url);
+ DPRINTF("PROXY DELETE PROVIDER prov=%sn", prov_name);
+ provider_t *prov = find_provider (prov_name);
+
+ // don't allow removal of current main_prov.
+ if (prov == main_prov)
+ prov = NULL;
+
+ int rc = prov ? MHD_HTTP_OK : MHD_HTTP_NOT_FOUND;
+ if (prov)
+ prov->deleted = 1;
+
+ error (0, 0, "DELETE PROV: rc=%d", rc);
+
+ free (prov_name);
+ MHD_queue_response(conn,rc,resp);
+ MHD_destroy_response(resp);
+
+ free_ms(ms);
+ return MHD_YES;
+}
+
+static int
+proxy_add_prov (void *cctx, struct MHD_Connection *conn, const char *url,
+ const char *method, const char *version, const char *data,
+ size_t *data_size, void **rctx)
+{
+ DPRINTF("PROXY ADD PROVIDER %sn",url);
+ struct MHD_Response *resp;
+ my_state *ms = *rctx;
+
+ (void)cctx;
+ (void)method;
+ (void)version;
+
+ if (ms->state == MS_NEW) {
+ ms->state = MS_NORMAL;
+ ms->url = (char *)url;
+ ms->dict = g_hash_table_new_full(
+ g_str_hash,g_str_equal,free,free);
+ ms->cleanup |= CLEANUP_DICT;
+ ms->post = MHD_create_post_processor(conn,4096,
+ prov_iterator,ms->dict);
+ ms->cleanup |= CLEANUP_POST;
+ }
+ else if (*data_size) {
+ MHD_post_process(ms->post,data,*data_size);
+ *data_size = 0;
+ }
+ else {
+ int rc = MHD_HTTP_BAD_REQUEST;
+ char *prov_name = url_to_provider_name (url);
+ /* We're about to insert "name -> $prov_name".
+ Ensure there is no "name" key already there. */
+ const char *name = g_hash_table_lookup (ms->dict, "name");
+ if (name) {
+ fprintf(stderr,
+ "add_provider: do not specify name: name=%sn",
+ name);
+ return MHD_NO;
+ // FIXME: be careful that this does not leak "ms"
+ }
+ // FIXME: unchecked strdup
+ g_hash_table_insert(ms->dict,strdup("name"),prov_name);
+
+ if (validate_provider (ms->dict)) {
+ if (!add_provider (ms->dict)) {
+ DPRINTF("add provider failedn");
+ } else {
+ rc = MHD_HTTP_OK;
+ }
+ }
+ else {
+ DPRINTF("invalid providern");
+ }
+ resp = MHD_create_response_from_data(0,NULL,MHD_NO,MHD_NO);
+ if (!resp) {
+ fprintf(stderr,"MHD_crfd failedn");
+ return MHD_NO;
+ }
+ MHD_queue_response(conn,rc,resp);
+ MHD_destroy_response(resp);
+ free_ms(ms);
+ }
+
+ return MHD_YES;
+}
+
static int
proxy_create_bucket (void *cctx, struct MHD_Connection *conn, const char *url,
const char *method, const char *version, const char *data,
@@ -1753,6 +1877,10 @@ static const rule my_rules[] = {
"GET", URL_PROVLIST, proxy_list_provs },
{ /* update a provider */
"POST", URL_PROVLIST, proxy_update_prov },
+ { /* create a provider */
+ "POST", URL_PROVIDER, proxy_add_prov },
+ { /* delete a provider */
+ "DELETE", URL_PROVIDER, proxy_delete_prov },
{ NULL, 0, NULL }
};
@@ -1806,6 +1934,12 @@ parse_url (const char *url, my_state *ms)
}
}
+ if (eindex == URL_OBJECT
+ && !strcmp (parts[URL_BUCKET], "_providers"))
+ eindex = URL_PROVIDER;
+
+ DPRINTF("parse_url: %d: %s %s %s", eindex, parts[URL_BUCKET],
+ parts[URL_OBJECT], parts[URL_ATTR]);
return eindex;
}
diff --git a/setup.c b/setup.c
index 2a03f40..86061d1 100644
--- a/setup.c
+++ b/setup.c
@@ -27,6 +27,7 @@
#include <string.h>
#include <strings.h>
#include <unistd.h>
+#include <assert.h>
#include <jansson.h>
@@ -71,8 +72,74 @@ static GHashTable *prov_hash = NULL;
provider_t *main_prov = NULL;
provider_t *master_prov = NULL;
+int
+validate_provider (GHashTable *h)
+{
+ const char *name = g_hash_table_lookup (h, "name");
+ assert (name);
+ const char *type = g_hash_table_lookup (h, "type");
+ if (type == NULL) {
+ error (0, 0, "provider %s has no type", name);
+ return 0;
+ }
+
+ unsigned int needs;
+ if (!strcasecmp(type,"s3") || !strcasecmp(type,"cf")) {
+ needs = NEED_SERVER | NEED_CREDS;
+ } else if (!strcasecmp(type,"http")) {
+ needs = NEED_SERVER;
+ } else if (!strcasecmp(type,"fs")) {
+ needs = NEED_PATH;
+ } else {
+ error (0, 0, "provider %s has invalid type: %s", name, type);
+ return 0;
+ }
+
+ int ok = 1;
+ if (needs & NEED_SERVER) {
+ const char *host = g_hash_table_lookup (h, "host");
+ if (!host) {
+ error (0, 0, "%s: %s-provider requires a host", name, type);
+ ok = 0;
+ }
+ const char *port = g_hash_table_lookup (h, "port");
+ if (!port) {
+ error (0, 0, "%s: %s-provider requires a port", name, type);
+ ok = 0;
+ }
+ // ensure port is a positive integer with 5 or fewer digits
+ if (5 < strlen (port) || strcspn (port, "0123456789")) {
+ error (0, 0, "%s: %s-provider: invalid port: %s", name, type, port);
+ ok = 0;
+ }
+ }
+
+ if (needs & NEED_CREDS) {
+ const char *key = g_hash_table_lookup (h, "key");
+ if (!key) {
+ error (0, 0, "%s: %s-provider requires a key", name, type);
+ ok = 0;
+ }
+ const char *secret = g_hash_table_lookup (h, "secret");
+ if (!secret) {
+ error (0, 0, "%s: %s-provider requires a secret", name, type);
+ ok = 0;
+ }
+ }
+
+ if (needs & NEED_PATH) {
+ const char *path = g_hash_table_lookup (h, "path");
+ if (!path) {
+ error (0, 0, "%s: %s-provider requires a path", name, type);
+ ok = 0;
+ }
+ }
+
+ return ok;
+}
+
static int
-validate_server (unsigned int i)
+json_validate_server (unsigned int i)
{
json_t *server;
json_t *elem;
@@ -209,6 +276,7 @@ convert_provider (int i, provider_t *out)
out->username = dup_json_string(server,"key");
out->password = dup_json_string(server,"secret");
out->path = dup_json_string(server,"path");
+ /* FIXME: detect failed "dup_*" calls. */
/* TBD: do this a cleaner way. */
if (!strcasecmp(out->type,"s3")) {
@@ -231,6 +299,7 @@ convert_provider (int i, provider_t *out)
iter = json_object_iter(server);
while (iter) {
key = json_object_iter_key(iter);
+ error(0,0,"convert-provider: ITER key: %s",key);
if (!is_reserved_attr(key)) {
value = json_string_value(json_object_iter_value(iter));
if (value) {
@@ -249,10 +318,100 @@ convert_provider (int i, provider_t *out)
}
out->token = NULL;
+ out->deleted = 0;
return 1;
}
+int
+add_provider (GHashTable *h)
+{
+ char *name = g_hash_table_lookup (h, "name");
+ assert (name);
+
+ provider_t *prov = calloc (1, sizeof *prov);
+ if (prov == NULL)
+ return 0;
+
+ prov->name = strdup (name);
+ if (prov->name == NULL)
+ goto fail;
+
+ prov->type = g_hash_table_lookup(h,"type");
+ if (prov->type == NULL)
+ goto fail;
+ prov->type = strdup (prov->type);
+ if (prov->type == NULL)
+ goto fail;
+
+ prov->host = g_hash_table_lookup(h,"host");
+ prov->port = atoi(g_hash_table_lookup(h,"port"));
+ /* TBD: change key/secret field names to username/password */
+ prov->username = g_hash_table_lookup(h,"key");
+ prov->password = g_hash_table_lookup(h,"secret");
+ prov->path = g_hash_table_lookup(h,"path");
+
+ if (prov->host)
+ prov->host = strdup (prov->host);
+ if (prov->username)
+ prov->username = strdup (prov->username);
+ if (prov->password)
+ prov->password = strdup (prov->password);
+ if (prov->path)
+ prov->path = strdup (prov->path);
+
+ /* TBD: do this a cleaner way. */
+ if (!strcasecmp(prov->type,"s3"))
+ prov->func_tbl = &s3_func_tbl;
+ else if (!strcasecmp(prov->type,"http"))
+ prov->func_tbl = &curl_func_tbl;
+ else if (!strcasecmp(prov->type,"cf"))
+ prov->func_tbl = &cf_func_tbl;
+ else if (!strcasecmp(prov->type,"fs"))
+ prov->func_tbl = &fs_func_tbl;
+ else
+ prov->func_tbl = &bad_func_tbl;
+
+ prov->attrs = g_hash_table_new_full(g_str_hash,g_str_equal,free,free);
+ // FIXME: can't the above fail?
+
+ GHashTableIter iter;
+ g_hash_table_iter_init (&iter, h);
+ while (1) {
+ gpointer key;
+ gpointer val;
+ if (!g_hash_table_iter_next (&iter, &key, &val))
+ break;
+
+ if (!is_reserved_attr(key)) {
+ if (val) {
+ error(0,0,"no value for %s", (char *)key);
+ continue;
+ }
+ DPRINTF("%p.%s = %sn",prov, (char *)key, (char *)val);
+ g_hash_table_insert(prov->attrs, strdup(key), strdup(val));
+ // FIXME: check strdup for failure
+ }
+ }
+
+ /* Note that we must strdup "name", since here it's a key, but above
it's a
+ value. Not using // strdup here would lead to a use-after-free bug. */
+ // FIXME: check strdup for failure
+ g_hash_table_insert(prov_hash,strdup(name),prov);
+
+ return 1;
+
+ fail:
+ free ((char *) prov->name);
+ free ((char *) prov->type);
+ free ((char *) prov->host);
+ free ((char *) prov->username);
+ free ((char *) prov->password);
+ free ((char *) prov->path);
+ free (prov);
+ return 0;
+}
+
static const char *
parse_config_inner (void)
{
@@ -274,7 +433,7 @@ parse_config_inner (void)
}
for (i = 0; i < nservers; ++i) {
- if (!validate_server(i)) {
+ if (!json_validate_server(i)) {
goto err;
}
}
@@ -402,7 +561,7 @@ auto_config(void)
return primary;
}
-const provider_t *
+provider_t *
get_provider (const char *name)
{
if (!prov_hash || !name || (*name == '0')) {
@@ -411,6 +570,18 @@ get_provider (const char *name)
return g_hash_table_lookup(prov_hash,name);
}
+provider_t *
+find_provider (const char *name)
+{
+ if (!prov_hash || !name || (*name == '0')) {
+ return NULL;
+ }
+
+ provider_t *p = g_hash_table_lookup(prov_hash, name);
+
+ return p;
+}
+
const char *
get_provider_value (const provider_t *prov, const char *fname)
{
diff --git a/setup.h b/setup.h
index e70cffa..11d2207 100644
--- a/setup.h
+++ b/setup.h
@@ -26,6 +26,7 @@ typedef struct _provider {
const char *type;
const char *host;
int port;
+ int deleted;
const char *username;
const char *password;
const char *path;
@@ -38,14 +39,17 @@ provider_t *main_prov;
provider_t *master_prov;
const char *parse_config (char *);
-const provider_t *get_provider (const char *name);
-void update_provider (const char *provname,
+provider_t *get_provider (const char *name);
+void update_provider (const char *provname,
const char *username,
const char *password);
const char *get_provider_value (const provider_t *prov,
const char *fname);
void init_prov_iter (GHashTableIter *iter);
-const char *auto_config (void);
+const char *auto_config (void);
+int validate_provider (GHashTable *h);
+provider_t *find_provider (const char *name);
+int add_provider (GHashTable *h);
#endif
diff --git a/t/basic b/t/basic
index 6a30fcc..fc42ac4 100644
--- a/t/basic
+++ b/t/basic
@@ -311,14 +311,45 @@ echo bye | curl -f -T - $bucket/trunc_test || fail=1
cat FS/b1/trunc_test
test "$(cat FS/b1/trunc_test)" = bye || fail=1
+# TBD: add attribute-delete tests when that functionality is implemented
+
+# TBD: add white-box tests for attributes in mongo
+
+# Add a provider:
+p1_url=http://localhost:$port/_providers/PROVIDER-1
+curl -d type=s3 -dhost=localhost -dport=80 -dkey=u -dsecret=p + $p1_url || fail=1
+
+# Ensure it was added
+curl
http://localhost:$port/_providers > p || fail=1
+grep PROVIDER-1 p || fail=1
+
+# Add another provider:
+p2_url=http://localhost:$port/_providers/PROVIDER-2
+curl -dtype=http -dhost=localhost -dport=9091 $p2_url || fail=1
+# Ensure it was added.
+curl
http://localhost:$port/_providers > p || fail=1
+grep PROVIDER-2 p || fail=1
+
+# Delete a provider.
+curl -f -X DELETE $p2_url 2> p || fail=1
+# Ensure it was deleted.
+curl
http://localhost:$port/_providers > p || fail=1
+grep PROVIDER-2 p && { warn_ $ME_: provider deletion failed; fail=1; }
+
+# Delete a non-existent provider.
+curl -f -X DELETE
http://localhost:$port/_providers/no-such
+test $? = 22 || fail=1
+# FIXME ensure it fails
+cat p
+
+curl
http://localhost:$port/_providers > p || fail=1
+cat p
+
# Test "headless" operation (no access to metadata DB).
kill -9 $mongo_pid
cleanup_() { kill $iwhd_pid; }
curl $bucket/attr_put > f3copy
test "$(cat f3copy)" = "nothing" || fail=1
-# TBD: add attribute-delete tests when that functionality is implemented
-
-# TBD: add white-box tests for attributes in mongo
-
Exit $fail
-----------------------------------------------------------------------
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")