PERFORCE change 122024 for review
Fredrik Lindberg
fli at FreeBSD.org
Wed Jun 20 10:52:20 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=122024
Change 122024 by fli at fli_genesis on 2007/06/20 10:52:02
- Do reference counting on records and record types so they can
be released when no longer needed.
- Make record_type_*() functions non-static.
- Add a function to manipulate the name of a record in-place.
- Add a function to manipulate resource data in-place.
- Add functions to traverse records, record types and resources.
- Reverse the logic of the memory allocation flag.
- Add macros to set the parent (owner).
- Add a NOINIT flag, allows *_get() to be used as search functions.
- Follow hash table changes.
- Add debugging printouts.
Affected files ...
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/record.c#2 edit
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/record.h#2 edit
Differences ...
==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/record.c#2 (text+ko) ====
@@ -29,10 +29,10 @@
#include <string.h>
#include "record.h"
+#include "log.h"
-static int record_type_get(struct record *, struct record_type **,
- int, uint16_t);
-static void record_type_release(struct record_type *);
+#define record_aquire(r) (r)->r_refcnt++;
+#define record_type_aquire(rt) (rt)->rt_refcnt++;
/*
* Initialize a record set for `class'
@@ -47,7 +47,8 @@
}
static void
-rec_free(struct hashtbl *ht, void *key, size_t keylen, void *data)
+rec_free(__unused struct hashtbl *ht, __unused const void *key,
+ __unused size_t keylen, void *data, __unused void *arg)
{
struct record *r = (struct record *)data;
struct record_type *rt, *rt2;
@@ -73,7 +74,7 @@
records_destroy(struct records *recs)
{
- hashtbl_walk(&recs->r_recs, rec_free);
+ hashtbl_walk(&recs->r_recs, rec_free, NULL);
hashtbl_destroy(&recs->r_recs);
MDNS_INIT_UNSET(recs, r_magic);
}
@@ -83,10 +84,10 @@
* recs - Record set
* r - Pointer to record
* name - Resource name
- * flags - RECORD_ALLOC will cause it to allocate memory if needed
+ * flags - RECORD_NOALLOC will supress memory allocation
*/
int
-record_get(struct records *recs, struct record **r, char *name, int flags)
+record_get(struct records *recs, struct record **r, int flags, char *name)
{
size_t len;
struct record *rec;
@@ -95,8 +96,19 @@
len = strlen(name);
rec = hashtbl_find(&recs->r_recs, name, len);
+
+ if (rec == NULL && (flags & RECORD_NOINIT)) {
+ *r = NULL;
+ return (0);
+ }
+
+ if (len > MDNS_RECORD_LEN) {
+ *r = NULL;
+ return (-1);
+ }
+
if (rec == NULL) {
- if (flags & RECORD_ALLOC)
+ if (!(flags & RECORD_NOALLOC))
*r = malloc(sizeof(struct record));
MDNS_INIT_SET((*r), r_magic);
(*r)->r_recs = recs;
@@ -110,7 +122,8 @@
else {
*r = rec;
}
- (*r)->r_refcnt++;
+ record_aquire(*r);
+ dprintf(DEBUG_REC, "Record aquired r=%x, refcnt=%d", *r, (*r)->r_refcnt);
return (0);
}
@@ -129,23 +142,66 @@
recs = r->r_recs;
MDNS_INIT_ASSERT(recs, r_magic);
- if (TAILQ_EMPTY(&r->r_list)) {
+ if (--r->r_refcnt == 0) {
+ assert(TAILQ_EMPTY(&r->r_list) == 1);
len = strlen(r->r_name);
hashtbl_del(&recs->r_recs, r->r_name, len);
MDNS_INIT_UNSET(r, r_magic);
- if (r->r_flags & RECORD_ALLOC)
+ if (!(r->r_flags & RECORD_NOALLOC))
free(r);
+ dprintf(DEBUG_REC, "References cleared on r=%x, removed", r);
}
+ else {
+ dprintf(DEBUG_REC, "Record released r=%x, refs=%d", r, r->r_refcnt);
+ }
}
/*
+ * Modify the name of a record in-place without releasing
+ * types and resources.
+ */
+void
+record_setname(struct record *r, char *name)
+{
+ struct records *recs;
+ size_t len;
+
+ MDNS_INIT_ASSERT(r, r_magic);
+ recs = r->r_recs;
+ MDNS_INIT_ASSERT(recs, r_magic);
+
+ len = strlen(r->r_name);
+ hashtbl_del(&recs->r_recs, r->r_name, len);
+ len = strlen(name);
+ memcpy(r->r_name, name, len+1);
+ hashtbl_add(&recs->r_recs, r->r_name, len, r, 0);
+ dprintf(DEBUG_REC, "Record name set to %s on r=%x", r->r_name, r);
+}
+
+/*
+ * Lookup if a record exists
+ */
+struct record *
+record_find(struct records *recs, char *name)
+{
+ struct record *r;
+ size_t len;
+
+ MDNS_INIT_ASSERT(recs, r_magic);
+
+ len = strlen(name);
+ r = hashtbl_find(&recs->r_recs, name, len);
+ return (r);
+}
+
+/*
* Get a record type for a record, will be intialized if needed
* r - Record
* rt - Pointer to the new record type
- * flags - RECORD_ALLOC will cause it to allocated memory if needed
+ * flags - RECORD_NOALLOC will supress memory allocation
* type - DNS type
*/
-static int
+int
record_type_get(struct record *r, struct record_type **rt, int flags,
uint16_t type)
{
@@ -157,9 +213,13 @@
if (type == rt2->rt_type)
break;
}
+ if (rt2 == NULL && (flags & RECORD_NOINIT)) {
+ *rt = NULL;
+ return (0);
+ }
if (rt2 == NULL) {
- if (flags & RECORD_ALLOC)
+ if (!(flags & RECORD_NOALLOC))
*rt = malloc(sizeof(struct record_type));
MDNS_INIT_SET((*rt), rt_magic);
(*rt)->rt_parent = NULL;
@@ -167,6 +227,7 @@
(*rt)->rt_flags = flags;
(*rt)->rt_record = r;
(*rt)->rt_refcnt = 0;
+ record_aquire(r);
TAILQ_INIT(&((*rt)->rt_list));
TAILQ_FOREACH(rt2, &r->r_list, rt_next) {
if (type > rt2->rt_type)
@@ -180,7 +241,9 @@
else {
*rt = rt2;
}
- (*rt)->rt_refcnt++;
+ record_type_aquire(*rt);
+ dprintf(DEBUG_REC, "Record type aquired rt=%x, refcnt=%d", *rt,
+ (*rt)->rt_refcnt);
return (0);
}
@@ -189,7 +252,7 @@
* was the last reference.
* rt - Record type to release
*/
-static void
+void
record_type_release(struct record_type *rt)
{
struct record *r;
@@ -199,13 +262,17 @@
r = rt->rt_record;
TAILQ_REMOVE(&r->r_list, rt, rt_next);
MDNS_INIT_UNSET(rt, rt_magic);
- if (rt->rt_flags & RECORD_ALLOC)
+ if (!(rt->rt_flags & RECORD_NOALLOC))
free(rt);
+ dprintf(DEBUG_REC, "References cleared on rt=%x, removed", rt);
record_release(r);
}
+ else {
+ dprintf(DEBUG_REC, "Record type released rt=%x, refcnt=%d",
+ rt, rt->rt_refcnt);
+ }
}
-
/*
* Add a resource record to a resource type
* r - Parent record
@@ -223,17 +290,17 @@
MDNS_INIT_ASSERT(r, r_magic);
- record_type_get(r, &rt, RECORD_ALLOC, type);
- if (flags & RECORD_ALLOC)
+ record_type_get(r, &rt, 0, type);
+ if (!(flags & RECORD_NOALLOC))
*rr = malloc(sizeof(struct record_res));
MDNS_INIT_SET((*rr), rr_magic);
(*rr)->rr_parent = NULL;
(*rr)->rr_flags = flags;
- (*rr)->rr_data = data;
+ (*rr)->rr_data = data; /* FIXME: assumption, new flag */
(*rr)->rr_len = dlen;
(*rr)->rr_type = rt;
TAILQ_INSERT_TAIL(&rt->rt_list, *rr, rr_next);
-
+ dprintf(DEBUG_REC, "Resource rr=%x added on r=%x, rt=%x", *rr, r, rt);
return (0);
}
@@ -252,13 +319,27 @@
MDNS_INIT_ASSERT(rt, rt_magic);
flags = rr->rr_flags;
TAILQ_REMOVE(&rt->rt_list, rr, rr_next);
- free(rr->rr_data); /* XXX asumption */
+ free(rr->rr_data); /* FIXME assumption */
record_type_release(rt);
MDNS_INIT_UNSET(rr, rr_magic);
- if (flags & RECORD_ALLOC)
+ if (!(flags & RECORD_NOALLOC))
free(rr);
+ dprintf(DEBUG_REC, "Resource rr=%x removed, rt=%x", rr, rt);
+}
+
+void
+record_res_setdata(struct record_res *rr, void *data, size_t dlen)
+{
+
+ MDNS_INIT_ASSERT(rr, rr_magic);
+ free(rr->rr_data); /* FIXME: assumption */
+ rr->rr_data = data;
+ rr->rr_len = dlen;
+ dprintf(DEBUG_REC, "Resource data set on rr=%x, data=%x, dlen=%d",
+ rr, data, dlen);
}
+
/*
* Returns a pointer to the first resource record identified by (name, type)
* recs - Record set
@@ -290,3 +371,67 @@
rr = TAILQ_FIRST(&rt->rt_list);
return (rr);
}
+
+static void
+rec_walk(__unused struct hashtbl *ht, __unused const void *key,
+ __unused size_t keylen, void *data, void *arg)
+{
+ void **args = (void **)arg;
+ record_foreach cb = args[0];
+ void *cbarg = args[1];
+ struct record *r = data;
+
+ cb(r, cbarg);
+}
+
+void
+records_foreach(struct records *recs, record_foreach cb, void *arg)
+{
+ void *args[]= {cb, arg};
+
+ MDNS_INIT_ASSERT(recs, r_magic);
+ hashtbl_walk(&recs->r_recs, rec_walk, (void *)args);
+}
+
+void
+record_foreach_type(struct record *r, record_type_foreach cb, void *arg)
+{
+ struct record_type *rt, *rt2;
+
+ MDNS_INIT_ASSERT(r, r_magic);
+ TAILQ_FOREACH_SAFE(rt, &r->r_list, rt_next, rt2) {
+ MDNS_INIT_ASSERT(rt, rt_magic);
+ cb(rt, arg);
+ }
+}
+
+void
+record_type_foreach_res(struct record_type *rt, record_res_foreach cb,
+ void *arg)
+{
+ struct record_res *rr, *rr_tmp;
+ struct record_res *rr_head, *rr_next, *rr_prev;
+
+ MDNS_INIT_ASSERT(rt, rt_magic);
+
+ rr = rr_head = TAILQ_FIRST(&rt->rt_list);
+ while (rr != NULL) {
+ MDNS_INIT_ASSERT(rr, rr_magic);
+ rr_next = TAILQ_NEXT(rr, rr_next);
+ rr_prev = TAILQ_PREV(rr, record_res_head, rr_next);
+
+ cb(rr, arg);
+
+ if (rr_head != TAILQ_FIRST(&rt->rt_list)) {
+ rr = rr_head = TAILQ_FIRST(&rt->rt_list);
+ }
+ else {
+ rr_tmp = TAILQ_NEXT(TAILQ_NEXT(rr_prev, rr_next), rr_next);
+ if (rr_tmp != NULL && rr_tmp != rr_next)
+ rr = rr_tmp;
+ else
+ rr = rr_next;
+ }
+ }
+
+}
==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/record.h#2 (text+ko) ====
@@ -74,7 +74,7 @@
int rt_type;
int rt_flags;
size_t rt_refcnt;
- TAILQ_HEAD(, record_res) rt_list;
+ TAILQ_HEAD(record_res_head, record_res) rt_list;
};
/*
@@ -92,19 +92,44 @@
char r_name[MDNS_RECORD_LEN];
};
-#define RECORD_ALLOC 0x01
+/*
+ * Flags used with record_* functions
+ */
+#define RECORD_NOINIT 0x01 /* Do not initialize, assumes valid ptr */
+#define RECORD_NOALLOC 0x02 /* Do not allocate memory */
void records_init(struct records *, int);
void records_destroy(struct records *);
-int record_get(struct records *, struct record **, char *, int);
+void record_setname(struct record *, char *);
+int record_get(struct records *, struct record **, int, char *);
void record_release(struct record *);
+struct record * record_find(struct records *, char *);
+
+int record_type_get(struct record *, struct record_type **, int, uint16_t);
+void record_type_release(struct record_type *);
+
int record_res_add(struct record *, struct record_res **, int, uint16_t,
void *, size_t);
void record_res_del(struct record_res *);
struct record_res * record_res_find(struct records *, char *, uint16_t);
+void record_res_setdata(struct record_res *, void *, size_t);
-#define record_setparent(x, y) (x)->r_parent = y
-#define record_res_setparent(x, y) (x)->rr_parent = y
-#define record_res_getparent(x) (x)->rr_parent
+typedef void (*record_foreach)(struct record *, void *);
+typedef void (*record_type_foreach)(struct record_type *, void *);
+typedef void (*record_res_foreach)(struct record_res *, void *);
+
+void records_foreach(struct records *, record_foreach, void *);
+void record_foreach_type(struct record *, record_type_foreach, void *);
+void record_type_foreach_res(struct record_type *, record_res_foreach, void *);
+
+#define __getparent(x, f) (x)->f
+#define record_setparent(x, y) __getparent(x, r_parent) = y
+#define record_getparent(x) __getparent(x, r_parent)
+#define record_refcnt(x) (x)->r_refcnt
+#define record_type_setparent(x, y) __getparent(x, rt_parent) = y
+#define record_type_getparent(x) __getparent(x, rt_parent)
+#define record_type_refcnt(x) (x)->rt_refcnt
+#define record_res_setparent(x, y) __getparent(x, rr_parent) = y
+#define record_res_getparent(x) __getparent(x, rr_parent)
#endif /* _RECORD_H_ */
More information about the p4-projects
mailing list