Annotation of embedaddon/dhcp/omapip/handle.c, revision 1.1

1.1     ! misho       1: /* handle.c
        !             2: 
        !             3:    Functions for maintaining handles on objects. */
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
        !             7:  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
        !             8:  * Copyright (c) 1999-2003 by Internet Software Consortium
        !             9:  *
        !            10:  * Permission to use, copy, modify, and distribute this software for any
        !            11:  * purpose with or without fee is hereby granted, provided that the above
        !            12:  * copyright notice and this permission notice appear in all copies.
        !            13:  *
        !            14:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
        !            15:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            16:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
        !            17:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            18:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            19:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
        !            20:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            21:  *
        !            22:  *   Internet Systems Consortium, Inc.
        !            23:  *   950 Charter Street
        !            24:  *   Redwood City, CA 94063
        !            25:  *   <info@isc.org>
        !            26:  *   https://www.isc.org/
        !            27:  *
        !            28:  * This software has been written for Internet Systems Consortium
        !            29:  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
        !            30:  * To learn more about Internet Systems Consortium, see
        !            31:  * ``https://www.isc.org/''.  To learn more about Vixie Enterprises,
        !            32:  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
        !            33:  * ``http://www.nominum.com''.
        !            34:  */
        !            35: 
        !            36: #include "dhcpd.h"
        !            37: 
        !            38: #include <omapip/omapip_p.h>
        !            39: 
        !            40: /* The handle table is a hierarchical tree designed for quick mapping
        !            41:    of handle identifiers to objects.  Objects contain their own handle
        !            42:    identifiers if they have them, so the reverse mapping is also
        !            43:    quick.  The hierarchy is made up of table objects, each of which
        !            44:    has 120 entries, a flag indicating whether the table is a leaf
        !            45:    table or an indirect table, the handle of the first object covered
        !            46:    by the table and the first object after that that's *not* covered
        !            47:    by the table, a count of how many objects of either type are
        !            48:    currently stored in the table, and an array of 120 entries pointing
        !            49:    either to objects or tables.
        !            50: 
        !            51:    When we go to add an object to the table, we look to see if the
        !            52:    next object handle to be assigned is covered by the outermost
        !            53:    table.  If it is, we find the place within that table where the
        !            54:    next handle should go, and if necessary create additional nodes in
        !            55:    the tree to contain the new handle.  The pointer to the object is
        !            56:    then stored in the correct position.
        !            57:    
        !            58:    Theoretically, we could have some code here to free up handle
        !            59:    tables as they go out of use, but by and large handle tables won't
        !            60:    go out of use, so this is being skipped for now.  It shouldn't be
        !            61:    too hard to implement in the future if there's a different
        !            62:    application. */
        !            63: 
        !            64: omapi_handle_table_t *omapi_handle_table;
        !            65: omapi_handle_t omapi_next_handle = 1;  /* Next handle to be assigned. */
        !            66: 
        !            67: #define FIND_HAND  0
        !            68: #define CLEAR_HAND 1
        !            69: 
        !            70: static isc_result_t omapi_handle_lookup_in (omapi_object_t **,
        !            71:                                            omapi_handle_t,
        !            72:                                            omapi_handle_table_t *,
        !            73:                                            int);
        !            74: static isc_result_t omapi_object_handle_in_table (omapi_handle_t,
        !            75:                                                  omapi_handle_table_t *,
        !            76:                                                  omapi_object_t *);
        !            77: static isc_result_t omapi_handle_table_enclose (omapi_handle_table_t **);
        !            78: 
        !            79: isc_result_t omapi_object_handle (omapi_handle_t *h, omapi_object_t *o)
        !            80: {
        !            81:        isc_result_t status;
        !            82: 
        !            83:        if (o -> handle) {
        !            84:                *h = o -> handle;
        !            85:                return ISC_R_SUCCESS;
        !            86:        }
        !            87:        
        !            88:        if (!omapi_handle_table) {
        !            89:                omapi_handle_table = dmalloc (sizeof *omapi_handle_table, MDL);
        !            90:                if (!omapi_handle_table)
        !            91:                        return ISC_R_NOMEMORY;
        !            92:                memset (omapi_handle_table, 0, sizeof *omapi_handle_table);
        !            93:                omapi_handle_table -> first = 0;
        !            94:                omapi_handle_table -> limit = OMAPI_HANDLE_TABLE_SIZE;
        !            95:                omapi_handle_table -> leafp = 1;
        !            96:        }
        !            97: 
        !            98:        /* If this handle doesn't fit in the outer table, we need to
        !            99:           make a new outer table.  This is a while loop in case for
        !           100:           some reason we decide to do disjoint handle allocation,
        !           101:           where the next level of indirection still isn't big enough
        !           102:           to enclose the next handle ID. */
        !           103: 
        !           104:        while (omapi_next_handle >= omapi_handle_table -> limit) {
        !           105:                omapi_handle_table_t *new;
        !           106:                
        !           107:                new = dmalloc (sizeof *new, MDL);
        !           108:                if (!new)
        !           109:                        return ISC_R_NOMEMORY;
        !           110:                memset (new, 0, sizeof *new);
        !           111:                new -> first = 0;
        !           112:                new -> limit = (omapi_handle_table -> limit *
        !           113:                                               OMAPI_HANDLE_TABLE_SIZE);
        !           114:                new -> leafp = 0;
        !           115:                new -> children [0].table = omapi_handle_table;
        !           116:                omapi_handle_table = new;
        !           117:        }
        !           118: 
        !           119:        /* Try to cram this handle into the existing table. */
        !           120:        status = omapi_object_handle_in_table (omapi_next_handle,
        !           121:                                               omapi_handle_table, o);
        !           122:        /* If it worked, return the next handle and increment it. */
        !           123:        if (status == ISC_R_SUCCESS) {
        !           124:                *h = omapi_next_handle;
        !           125:                omapi_next_handle++;
        !           126:                return ISC_R_SUCCESS;
        !           127:        }
        !           128:        if (status != ISC_R_NOSPACE)
        !           129:                return status;
        !           130: 
        !           131:        status = omapi_handle_table_enclose (&omapi_handle_table);
        !           132:        if (status != ISC_R_SUCCESS)
        !           133:                return status;
        !           134: 
        !           135:        status = omapi_object_handle_in_table (omapi_next_handle,
        !           136:                                               omapi_handle_table, o);
        !           137:        if (status != ISC_R_SUCCESS)
        !           138:                return status;
        !           139:        *h = omapi_next_handle;
        !           140:        omapi_next_handle++;
        !           141: 
        !           142:        return ISC_R_SUCCESS;
        !           143: }
        !           144: 
        !           145: static isc_result_t omapi_object_handle_in_table (omapi_handle_t h,
        !           146:                                                  omapi_handle_table_t *table,
        !           147:                                                  omapi_object_t *o)
        !           148: {
        !           149:        omapi_handle_table_t *inner;
        !           150:        omapi_handle_t scale, index;
        !           151:        isc_result_t status;
        !           152: 
        !           153:        if (table -> first > h || table -> limit <= h)
        !           154:                return ISC_R_NOSPACE;
        !           155:        
        !           156:        /* If this is a leaf table, just stash the object in the
        !           157:           appropriate place. */
        !           158:        if (table -> leafp) {
        !           159:                status = (omapi_object_reference
        !           160:                          (&table -> children [h - table -> first].object,
        !           161:                           o, MDL));
        !           162:                if (status != ISC_R_SUCCESS)
        !           163:                        return status;
        !           164:                o -> handle = h;
        !           165:                return ISC_R_SUCCESS;
        !           166:        }
        !           167: 
        !           168:        /* Scale is the number of handles represented by each child of this
        !           169:           table.   For a leaf table, scale would be 1.   For a first level
        !           170:           of indirection, 120.   For a second, 120 * 120.   Et cetera. */
        !           171:        scale = (table -> limit - table -> first) / OMAPI_HANDLE_TABLE_SIZE;
        !           172: 
        !           173:        /* So the next most direct table from this one that contains the
        !           174:           handle must be the subtable of this table whose index into this
        !           175:           table's array of children is the handle divided by the scale. */
        !           176:        index = (h - table -> first) / scale;
        !           177:        inner = table -> children [index].table;
        !           178: 
        !           179:        /* If there is no more direct table than this one in the slot
        !           180:           we came up with, make one. */
        !           181:        if (!inner) {
        !           182:                inner = dmalloc (sizeof *inner, MDL);
        !           183:                if (!inner)
        !           184:                        return ISC_R_NOMEMORY;
        !           185:                memset (inner, 0, sizeof *inner);
        !           186:                inner -> first = index * scale + table -> first;
        !           187:                inner -> limit = inner -> first + scale;
        !           188:                if (scale == OMAPI_HANDLE_TABLE_SIZE)
        !           189:                        inner -> leafp = 1;
        !           190:                table -> children [index].table = inner;
        !           191:        }
        !           192: 
        !           193:        status = omapi_object_handle_in_table (h, inner, o);
        !           194:        if (status == ISC_R_NOSPACE) {
        !           195:                status = (omapi_handle_table_enclose
        !           196:                          (&table -> children [index].table));
        !           197:                if (status != ISC_R_SUCCESS)
        !           198:                        return status;
        !           199: 
        !           200:                return omapi_object_handle_in_table
        !           201:                        (h, table -> children [index].table, o);
        !           202:        }
        !           203:        return status;
        !           204: }
        !           205: 
        !           206: static isc_result_t omapi_handle_table_enclose (omapi_handle_table_t **table)
        !           207: {
        !           208:        omapi_handle_table_t *inner = *table;
        !           209:        omapi_handle_table_t *new;
        !           210:        int index, base, scale;
        !           211: 
        !           212:        /* The scale of the table we're enclosing is going to be the
        !           213:           difference between its "first" and "limit" members.  So the
        !           214:           scale of the table enclosing it is going to be that multiplied
        !           215:           by the table size. */
        !           216:        scale = (inner -> first - inner -> limit) * OMAPI_HANDLE_TABLE_SIZE;
        !           217: 
        !           218:        /* The range that the enclosing table covers is going to be
        !           219:           the result of subtracting the remainder of dividing the
        !           220:           enclosed table's first entry number by the enclosing
        !           221:           table's scale.  If handle IDs are being allocated
        !           222:           sequentially, the enclosing table's "first" value will be
        !           223:           the same as the enclosed table's "first" value. */
        !           224:        base = inner -> first - inner -> first % scale;
        !           225: 
        !           226:        /* The index into the enclosing table at which the enclosed table
        !           227:           will be stored is going to be the difference between the "first"
        !           228:           value of the enclosing table and the enclosed table - zero, if
        !           229:           we are allocating sequentially. */
        !           230:        index = (base - inner -> first) / OMAPI_HANDLE_TABLE_SIZE;
        !           231: 
        !           232:        new = dmalloc (sizeof *new, MDL);
        !           233:        if (!new)
        !           234:                return ISC_R_NOMEMORY;
        !           235:        memset (new, 0, sizeof *new);
        !           236:        new -> first = base;
        !           237:        new -> limit = base + scale;
        !           238:        if (scale == OMAPI_HANDLE_TABLE_SIZE)
        !           239:                new -> leafp = 0;
        !           240:        new -> children [index].table = inner;
        !           241:        *table = new;
        !           242:        return ISC_R_SUCCESS;
        !           243: }
        !           244: 
        !           245: isc_result_t omapi_handle_lookup (omapi_object_t **o, omapi_handle_t h)
        !           246: {
        !           247:        return(omapi_handle_lookup_in(o, h, omapi_handle_table, FIND_HAND));
        !           248: }
        !           249: 
        !           250: static isc_result_t omapi_handle_lookup_in (omapi_object_t **o,
        !           251:                                            omapi_handle_t h,
        !           252:                                            omapi_handle_table_t *table,
        !           253:                                            int op)
        !           254: {
        !           255:        omapi_handle_table_t *inner;
        !           256:        omapi_handle_t scale, index;
        !           257: 
        !           258:        if (!table || table->first > h || table->limit <= h)
        !           259:                return(ISC_R_NOTFOUND);
        !           260:        
        !           261:        /* If this is a leaf table, just grab the object. */
        !           262:        if (table->leafp) {
        !           263:                /* Not there? */
        !           264:                if (!table->children[h - table->first].object)
        !           265:                        return(ISC_R_NOTFOUND);
        !           266:                if (op == CLEAR_HAND) {
        !           267:                        table->children[h - table->first].object = NULL;
        !           268:                        return(ISC_R_SUCCESS);
        !           269:                } else {
        !           270:                        return(omapi_object_reference
        !           271:                               (o, table->children[h - table->first].object,
        !           272:                                MDL));
        !           273:                }
        !           274:        }
        !           275: 
        !           276:        /* Scale is the number of handles represented by each child of this
        !           277:           table.   For a leaf table, scale would be 1.   For a first level
        !           278:           of indirection, 120.   For a second, 120 * 120.   Et cetera. */
        !           279:        scale = (table->limit - table->first) / OMAPI_HANDLE_TABLE_SIZE;
        !           280: 
        !           281:        /* So the next most direct table from this one that contains the
        !           282:           handle must be the subtable of this table whose index into this
        !           283:           table's array of children is the handle divided by the scale. */
        !           284:        index = (h - table->first) / scale;
        !           285:        inner = table->children[index].table;
        !           286: 
        !           287:        return(omapi_handle_lookup_in(o, h, table->children[index].table, op));
        !           288: }
        !           289: 
        !           290: /* For looking up objects based on handles that have been sent on the wire. */
        !           291: isc_result_t omapi_handle_td_lookup (omapi_object_t **obj,
        !           292:                                     omapi_typed_data_t *handle)
        !           293: {
        !           294:        omapi_handle_t h;
        !           295: 
        !           296:        if (handle->type == omapi_datatype_int)
        !           297:                h = handle->u.integer;
        !           298:        else if (handle->type == omapi_datatype_data &&
        !           299:                 handle->u.buffer.len == sizeof h) {
        !           300:                memcpy(&h, handle->u.buffer.value, sizeof h);
        !           301:                h = ntohl(h);
        !           302:        } else
        !           303:                return(ISC_R_INVALIDARG);
        !           304:        return(omapi_handle_lookup(obj, h));
        !           305: }
        !           306: 
        !           307: isc_result_t omapi_handle_clear(omapi_handle_t h)
        !           308: {
        !           309:        return(omapi_handle_lookup_in(NULL, h, omapi_handle_table, CLEAR_HAND));
        !           310: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>