summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: b1208c3)
raw | patch | inline | side by side (parent: b1208c3)
author | Sebastian Harl <sh@tokkee.org> | |
Fri, 4 Jul 2014 18:38:52 +0000 (20:38 +0200) | ||
committer | Sebastian Harl <sh@tokkee.org> | |
Fri, 4 Jul 2014 18:38:52 +0000 (20:38 +0200) |
src/core/store.c | patch | blob | history | |
src/include/core/store.h | patch | blob | history | |
t/unit/core/store_test.c | patch | blob | history |
diff --git a/src/core/store.c b/src/core/store.c
index fc2a7f472d6dbdc0fb7111c2096cbfde38741d6f..323ed778b7c52fa76c8d492447781b2920695995 100644 (file)
--- a/src/core/store.c
+++ b/src/core/store.c
assert(parent_list);
+ if (last_update <= 0)
+ last_update = sdb_gettime();
+
old = STORE_OBJ(sdb_llist_search_by_name(parent_list, name));
if (old) {
if (old->last_update >= last_update) {
return status;
} /* store_obj */
-/* The host_lock has to be acquired before calling this function. */
static int
-store_host_obj(const char *hostname, int type, const char *name,
- sdb_time_t last_update, sdb_store_obj_t **updated_obj)
+store_attr(sdb_llist_t *attributes, const char *key, const sdb_data_t *value,
+ sdb_time_t last_update)
{
- char *cname = NULL;
- sdb_host_t *host;
- sdb_llist_t *parent_list;
+ sdb_store_obj_t *attr = NULL;
+ int status;
- int status = 0;
+ status = store_obj(attributes, SDB_ATTRIBUTE, key, last_update, &attr);
+ if (status < 0)
+ return status;
- if (last_update <= 0)
- last_update = sdb_gettime();
+ assert(attr);
+ if (sdb_data_copy(&ATTR(attr)->value, value))
+ return -1;
+ return status;
+} /* store_attr */
+
+/* The host_lock has to be acquired before calling this function. */
+static sdb_llist_t *
+get_host_children(const char *hostname, int type)
+{
+ char *cname = NULL;
+ sdb_host_t *host;
assert(hostname);
assert((type == SDB_SERVICE) || (type == SDB_ATTRIBUTE));
if (! host_list)
- return -1;
+ return NULL;
cname = sdb_plugin_cname(strdup(hostname));
if (! cname) {
sdb_log(SDB_LOG_ERR, "store: strdup failed");
- return -1;
+ return NULL;
}
host = lookup_host(cname);
- if (! host) {
- sdb_log(SDB_LOG_ERR, "store: Failed to store %s '%s' - "
- "host '%s' not found", SDB_STORE_TYPE_TO_NAME(type),
- name, hostname);
- free(cname);
- return -1;
- }
+ free(cname);
+ if (! host)
+ return NULL;
if (type == SDB_ATTRIBUTE)
- parent_list = host->attributes;
+ return host->attributes;
else
- parent_list = host->services;
-
- status = store_obj(parent_list, type, name,
- last_update, updated_obj);
-
- free(cname);
- return status;
-} /* store_host_obj */
+ return host->services;
+} /* get_host_children */
/*
* store_common_tojson serializes common object attributes to JSON.
if (! name)
return -1;
- if (last_update <= 0)
- last_update = sdb_gettime();
-
cname = sdb_plugin_cname(strdup(name));
if (! cname) {
sdb_log(SDB_LOG_ERR, "store: strdup failed");
const char *key, const sdb_data_t *value,
sdb_time_t last_update)
{
- int status;
-
- sdb_store_obj_t *updated_attr = NULL;
+ sdb_llist_t *attrs;
+ int status = 0;
if ((! hostname) || (! key))
return -1;
pthread_rwlock_wrlock(&host_lock);
- status = store_host_obj(hostname, SDB_ATTRIBUTE, key, last_update,
- &updated_attr);
-
- if (status >= 0) {
- assert(updated_attr);
- if (sdb_data_copy(&ATTR(updated_attr)->value, value))
- status = -1;
+ attrs = get_host_children(hostname, SDB_ATTRIBUTE);
+ if (! attrs) {
+ sdb_log(SDB_LOG_ERR, "store: Failed to store attribute '%s' - "
+ "host '%s' not found", key, hostname);
+ status = -1;
}
+ if (! status)
+ status = store_attr(attrs, key, value, last_update);
+
pthread_rwlock_unlock(&host_lock);
return status;
} /* sdb_store_attribute */
sdb_store_service(const char *hostname, const char *name,
sdb_time_t last_update)
{
- int status;
+ sdb_llist_t *services;
+
+ int status = 0;
if ((! hostname) || (! name))
return -1;
pthread_rwlock_wrlock(&host_lock);
- status = store_host_obj(hostname, SDB_SERVICE, name, last_update, NULL);
+ services = get_host_children(hostname, SDB_SERVICE);
+ if (! services) {
+ sdb_log(SDB_LOG_ERR, "store: Failed to store service '%s' - "
+ "host '%s' not found", name, hostname);
+ status = -1;
+ }
+
+ if (! status)
+ status = store_obj(services, SDB_SERVICE, name, last_update, NULL);
pthread_rwlock_unlock(&host_lock);
return status;
} /* sdb_store_service */
+int
+sdb_store_service_attr(const char *hostname, const char *service,
+ const char *key, const sdb_data_t *value, sdb_time_t last_update)
+{
+ sdb_llist_t *services;
+ sdb_service_t *svc;
+ int status = 0;
+
+ if ((! hostname) || (! service) || (! key))
+ return -1;
+
+ pthread_rwlock_wrlock(&host_lock);
+ services = get_host_children(hostname, SDB_SERVICE);
+ if (! services) {
+ sdb_log(SDB_LOG_ERR, "store: Failed to store attribute '%s' "
+ "for service '%s' - host '%ss' not found",
+ key, service, hostname);
+ pthread_rwlock_unlock(&host_lock);
+ return -1;
+ }
+
+ svc = SVC(sdb_llist_search_by_name(services, service));
+ if (! svc) {
+ sdb_log(SDB_LOG_ERR, "store: Failed to store attribute '%s' - "
+ "service '%s/%s' not found", key, hostname, service);
+ status = -1;
+ }
+
+ if (! status)
+ status = store_attr(svc->attributes, key, value, last_update);
+
+ pthread_rwlock_unlock(&host_lock);
+ return status;
+} /* sdb_store_service_attr */
+
int
sdb_store_host_tojson(sdb_store_obj_t *h, sdb_strbuf_t *buf, int flags)
{
index e273e7ca1aedb59702de8014c9efeb2c7ba7ffd9..1d64c4b7bee0a0f2d3944272521f3c74a85bc472 100644 (file)
--- a/src/include/core/store.h
+++ b/src/include/core/store.h
sdb_store_service(const char *hostname, const char *name,
sdb_time_t last_update);
+/*
+ * sdb_store_service_attr:
+ * Add/update a service's attribute in the store. If the attribute, identified
+ * by its key, already exists for the specified service, it will be updated to
+ * the specified value. If the references service (for the specified host)
+ * does not exist, an error will be reported. Any memory required for storing
+ * the entry will be allocated and managed by the store itself.
+ *
+ * Returns:
+ * - 0 on success
+ * - a positive value if the new entry is older than the currently stored
+ * entry (in this case, no update will happen)
+ * - a negative value on error
+ */
+int
+sdb_store_service_attr(const char *hostname, const char *service,
+ const char *key, const sdb_data_t *value, sdb_time_t last_update);
+
/*
* Conditionals may be used to lookup hosts from the store based on a
* conditional expression.
index 0a022e430508276e80563c7b37fc2fb494f6e511..6715a5b0868a49714b3a9e3664ff586e6455166c 100644 (file)
--- a/t/unit/core/store_test.c
+++ b/t/unit/core/store_test.c
}
END_TEST
+START_TEST(test_store_service_attr)
+{
+ struct {
+ const char *host;
+ const char *svc;
+ const char *attr;
+ const sdb_data_t value;
+ sdb_time_t last_update;
+ int expected;
+ } golden_data[] = {
+ { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
+ /* retry, it should still fail */
+ { "k", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
+ { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
+ /* retry, it should still fail */
+ { "l", "sX", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, -1 },
+ { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
+ { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 },
+ { "l", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 2, 0 },
+ { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
+ { "l", "s1", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 1 },
+ { "l", "s2", "a2", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
+ { "m", "s1", "a1", { SDB_TYPE_INTEGER, { .integer = 123 } }, 1, 0 },
+ };
+
+ size_t i;
+
+ sdb_store_host("m", 1);
+ sdb_store_host("l", 1);
+ sdb_store_service("m", "s1", 1);
+ sdb_store_service("l", "s1", 1);
+ sdb_store_service("l", "s2", 1);
+
+ for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
+ int status;
+
+ status = sdb_store_service_attr(golden_data[i].host,
+ golden_data[i].svc, golden_data[i].attr,
+ &golden_data[i].value, golden_data[i].last_update);
+ fail_unless(status == golden_data[i].expected,
+ "sdb_store_service_attr(%s, %s, %s, %d, %d) = %d; "
+ "expected: %d", golden_data[i].host, golden_data[i].svc,
+ golden_data[i].attr, golden_data[i].value.data.integer,
+ golden_data[i].last_update, status, golden_data[i].expected);
+ }
+}
+END_TEST
+
static void
verify_json_output(sdb_strbuf_t *buf, const char *expected, int flags)
{
tcase_add_test(tc, test_store_get_host);
tcase_add_test(tc, test_store_attr);
tcase_add_test(tc, test_store_service);
+ tcase_add_test(tc, test_store_service_attr);
tcase_add_test(tc, test_interval);
tcase_add_test(tc, test_iterate);
tcase_add_unchecked_fixture(tc, NULL, sdb_store_clear);