diff --git a/Makefile b/Makefile index 0987595df..af40c7b79 100644 --- a/Makefile +++ b/Makefile @@ -947,7 +947,8 @@ OBJS += src/mux_h2.o src/mux_fcgi.o src/mux_h1.o src/tcpcheck.o \ src/base64.o src/auth.o src/uri_auth.o src/time.o src/ebistree.o \ src/dynbuf.o src/wdt.o src/pipe.o src/init.o src/http_acl.o \ src/hpack-huff.o src/hpack-enc.o src/dict.o src/freq_ctr.o \ - src/ebtree.o src/hash.o src/dgram.o src/version.o src/proto_rhttp.o + src/ebtree.o src/hash.o src/dgram.o src/version.o src/proto_rhttp.o \ + src/guid.o ifneq ($(TRACE),) OBJS += src/calltrace.o diff --git a/include/haproxy/guid-t.h b/include/haproxy/guid-t.h new file mode 100644 index 000000000..41645d729 --- /dev/null +++ b/include/haproxy/guid-t.h @@ -0,0 +1,12 @@ +#ifndef _HAPROXY_GUID_T_H +#define _HAPROXY_GUID_T_H + +#include +#include + +struct guid_node { + struct ebpt_node node; /* attach point into GUID global tree */ + enum obj_type *obj_type; /* pointer to GUID obj owner */ +}; + +#endif /* _HAPROXY_GUID_T_H */ diff --git a/include/haproxy/guid.h b/include/haproxy/guid.h new file mode 100644 index 000000000..8c88a8866 --- /dev/null +++ b/include/haproxy/guid.h @@ -0,0 +1,15 @@ +#ifndef _HAPROXY_GUID_H +#define _HAPROXY_GUID_H + +#include + +extern struct eb_root guid_tree; + +void guid_init(struct guid_node *node); +int guid_insert(enum obj_type *obj_type, const char *uid, char **errmsg); +void guid_remove(struct guid_node *guid); +struct guid_node *guid_lookup(const char *uid); + +char *guid_name(const struct guid_node *guid); + +#endif /* _HAPROXY_GUID_H */ diff --git a/src/guid.c b/src/guid.c new file mode 100644 index 000000000..178353ba5 --- /dev/null +++ b/src/guid.c @@ -0,0 +1,99 @@ +#include + +#include +#include +#include + +/* GUID global tree */ +struct eb_root guid_tree = EB_ROOT_UNIQUE; + +/* Initialize members. */ +void guid_init(struct guid_node *guid) +{ + guid->node.key = NULL; + guid->node.node.leaf_p = NULL; +} + +/* Insert into GUID global tree with key . Must only be called on + * thread isolation. On failure, will be allocated with an error + * description. Caller is responsible to free it. + * + * Returns 0 on success else non-zero. + */ +int guid_insert(enum obj_type *objt, const char *uid, char **errmsg) +{ + struct guid_node *guid = NULL; + struct guid_node *dup; + struct ebpt_node *node; + char *dup_name = NULL; + + switch (obj_type(objt)) { + default: + /* No guid support for this objtype. */ + ABORT_NOW(); + return 0; + } + + guid->node.key = strdup(uid); + if (!guid->node.key) { + memprintf(errmsg, "key alloc failure"); + goto err; + } + + node = ebis_insert(&guid_tree, &guid->node); + if (node != &guid->node) { + dup = ebpt_entry(node, struct guid_node, node); + dup_name = guid_name(dup); + memprintf(errmsg, "duplicate entry with %s", dup_name); + goto err; + } + + guid->obj_type = objt; + return 0; + + err: + ha_free(&guid->node.key); + ha_free(&dup_name); + return 1; +} + +/* Remove node from GUID global tree. Must only be called on thread + * isolation. Safe to call even if node is not currently stored. + */ +void guid_remove(struct guid_node *guid) +{ + ebpt_delete(&guid->node); + ha_free(&guid->node.key); +} + +/* Retrieve an instance from GUID global tree with key . + * + * Returns the GUID instance or NULL if key not found. + */ +struct guid_node *guid_lookup(const char *uid) +{ + struct ebpt_node *node = NULL; + struct guid_node *guid = NULL; + + node = ebis_lookup(&guid_tree, uid); + if (node) + guid = ebpt_entry(node, struct guid_node, node); + + return guid; +} + +/* Generate a user-friendly description for the instance attached via + * node. The string is dynamically allocated and the caller is responsible to + * free it. + * + * Returns a pointer to the dynamically allocated message. + */ +char *guid_name(const struct guid_node *guid) +{ + switch (obj_type(guid->obj_type)) { + default: + break; + } + + return NULL; +}