From owner-p4-projects@FreeBSD.ORG Wed Jun 20 10:52:20 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 48BEB16A46B; Wed, 20 Jun 2007 10:52:20 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 01F3D16A400 for ; Wed, 20 Jun 2007 10:52:20 +0000 (UTC) (envelope-from fli@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id E614513C44C for ; Wed, 20 Jun 2007 10:52:19 +0000 (UTC) (envelope-from fli@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l5KAqJSN006670 for ; Wed, 20 Jun 2007 10:52:19 GMT (envelope-from fli@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l5KAqJTu006661 for perforce@freebsd.org; Wed, 20 Jun 2007 10:52:19 GMT (envelope-from fli@FreeBSD.org) Date: Wed, 20 Jun 2007 10:52:19 GMT Message-Id: <200706201052.l5KAqJTu006661@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to fli@FreeBSD.org using -f From: Fredrik Lindberg To: Perforce Change Reviews Cc: Subject: PERFORCE change 122024 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 Jun 2007 10:52:20 -0000 http://perforce.freebsd.org/chv.cgi?CH=122024 Change 122024 by fli@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 #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_ */