2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-27 20:49:04 +00:00
bind/lib/omapi/object.c

166 lines
4.5 KiB
C
Raw Normal View History

2000-01-04 20:04:42 +00:00
/*
* Copyright (C) 1996, 1997, 1998, 1999 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
2000-01-14 23:10:04 +00:00
/* $Id: object.c,v 1.4 2000/01/14 23:10:03 tale Exp $ */
2000-01-04 20:04:42 +00:00
/* Principal Author: Ted Lemon */
/*
* Functions supporting memory allocation for the object management protocol.
*/
#include <string.h> /* memset */
#include <isc/assertions.h>
#include <isc/error.h>
#include <omapi/private.h>
2000-01-06 03:36:32 +00:00
isc_result_t
2000-01-14 23:10:04 +00:00
omapi_object_new(omapi_object_t **object, omapi_object_type_t *type,
size_t size)
2000-01-06 03:36:32 +00:00
{
omapi_object_t *new;
REQUIRE(object != NULL && *object == NULL);
new = isc_mem_get(omapi_mctx, size);
if (new == NULL)
return (ISC_R_NOMEMORY);
memset(new, 0, size);
new->object_size = size;
new->refcnt = 1;
new->type = type;
*object = new;
return (ISC_R_SUCCESS);
}
2000-01-04 20:04:42 +00:00
void
omapi_object_reference(omapi_object_t **r, omapi_object_t *h,
const char *name)
{
REQUIRE(r != NULL && *r == NULL);
REQUIRE(h != NULL);
(void)name; /* Unused. */
*r = h;
h->refcnt++;
}
void
omapi_object_dereference(omapi_object_t **h, const char *name) {
int outer_reference = 0;
int inner_reference = 0;
int handle_reference = 0;
int extra_references;
omapi_object_t *p;
REQUIRE(h != NULL && *h != NULL);
REQUIRE((*h)->refcnt > 0);
/*
2000-01-14 23:10:04 +00:00
* See if this object's inner object refers back to it, but don't
2000-01-04 20:04:42 +00:00
* count this as a reference if we're being asked to free the
* reference from the inner object.
*/
2000-01-14 23:10:04 +00:00
/*
* XXXDCL my wording
* Note whether the object being dereference has an inner object, but
* only if the inner object's own outer pointer is not what is
* being dereferenced.
* (XXXDCL when does it happen that way ?)
*/
2000-01-04 20:04:42 +00:00
if ((*h)->inner != NULL && (*h)->inner->outer != NULL &&
h != &((*h)->inner->outer))
inner_reference = 1;
/*
* Ditto for the outer object.
*/
if ((*h)->outer != NULL && (*h)->outer->inner != NULL &&
h != &((*h)->outer->inner))
outer_reference = 1;
/*
* Ditto for the handle object. The code below assumes that
* the only reason we'd get a dereference from the handle
* table is if this function does it - otherwise we'd have to
* traverse the handle table to find the address where the
* reference is stored and compare against that, and we don't
* want to do that if we can avoid it.
*/
if ((*h)->handle != 0)
handle_reference = 1;
/*
* If we are getting rid of the last reference other than
* references to inner and outer objects, or from the handle
* table, then we must examine all the objects in either
* direction to see if they hold any non-inner, non-outer,
* non-handle-table references. If not, we need to free the
* entire chain of objects.
*/
if ((*h)->refcnt ==
inner_reference + outer_reference + handle_reference + 1) {
if (inner_reference != 0 ||
outer_reference != 0 ||
handle_reference != 0) {
/*
* XXXTL we could check for a reference from the
* handle table here.
*/
extra_references = 0;
2000-01-14 23:10:04 +00:00
2000-01-04 20:04:42 +00:00
for (p = (*h)->inner;
p != NULL && extra_references == 0;
p = p->inner) {
extra_references += p->refcnt - 1;
if (p->inner != NULL)
--extra_references;
if (p->handle != 0)
--extra_references;
}
2000-01-14 23:10:04 +00:00
2000-01-04 20:04:42 +00:00
for (p = (*h)->outer;
p != NULL && extra_references == 0;
p = p->outer) {
extra_references += p->refcnt - 1;
if (p->outer != NULL)
--extra_references;
if (p->handle != 0)
--extra_references;
}
} else
extra_references = 0;
if (extra_references == 0) {
if (inner_reference != 0)
OBJECT_DEREF(&(*h)->inner->outer, name);
if (outer_reference != 0)
OBJECT_DEREF(&(*h)->outer->inner, name);
if ((*h)->type->destroy != NULL)
(*((*h)->type->destroy))(*h, name);
isc_mem_put(omapi_mctx, *h, (*h)->object_size);
}
}
*h = NULL;
}