counter.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /*! \file */
00018 
00019 #include <config.h>
00020 
00021 #include <stddef.h>
00022 
00023 #include <isc/counter.h>
00024 #include <isc/magic.h>
00025 #include <isc/mem.h>
00026 #include <isc/util.h>
00027 
00028 #define COUNTER_MAGIC                   ISC_MAGIC('C', 'n', 't', 'r')
00029 #define VALID_COUNTER(r)                ISC_MAGIC_VALID(r, COUNTER_MAGIC)
00030 
00031 struct isc_counter {
00032         unsigned int    magic;
00033         isc_mem_t       *mctx;
00034         isc_mutex_t     lock;
00035         unsigned int    references;
00036         unsigned int    limit;
00037         unsigned int    used;
00038 };
00039 
00040 isc_result_t
00041 isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) {
00042         isc_result_t result;
00043         isc_counter_t *counter;
00044 
00045         REQUIRE(counterp != NULL && *counterp == NULL);
00046 
00047         counter = isc_mem_get(mctx, sizeof(*counter));
00048         if (counter == NULL)
00049                 return (ISC_R_NOMEMORY);
00050 
00051         result = isc_mutex_init(&counter->lock);
00052         if (result != ISC_R_SUCCESS) {
00053                 isc_mem_put(mctx, counter, sizeof(*counter));
00054                 return (result);
00055         }
00056 
00057         counter->mctx = NULL;
00058         isc_mem_attach(mctx, &counter->mctx);
00059 
00060         counter->references = 1;
00061         counter->limit = limit;
00062         counter->used = 0;
00063 
00064         counter->magic = COUNTER_MAGIC;
00065         *counterp = counter;
00066         return (ISC_R_SUCCESS);
00067 }
00068 
00069 isc_result_t
00070 isc_counter_increment(isc_counter_t *counter) {
00071         isc_result_t result = ISC_R_SUCCESS;
00072 
00073         LOCK(&counter->lock);
00074         counter->used++;
00075         if (counter->limit != 0 && counter->used >= counter->limit)
00076                 result = ISC_R_QUOTA;
00077         UNLOCK(&counter->lock);
00078 
00079         return (result);
00080 }
00081 
00082 unsigned int
00083 isc_counter_used(isc_counter_t *counter) {
00084         REQUIRE(VALID_COUNTER(counter));
00085 
00086         return (counter->used);
00087 }
00088 
00089 void
00090 isc_counter_setlimit(isc_counter_t *counter, int limit) {
00091         REQUIRE(VALID_COUNTER(counter));
00092 
00093         LOCK(&counter->lock);
00094         counter->limit = limit;
00095         UNLOCK(&counter->lock);
00096 }
00097 
00098 void
00099 isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) {
00100         REQUIRE(VALID_COUNTER(source));
00101         REQUIRE(targetp != NULL && *targetp == NULL);
00102 
00103         LOCK(&source->lock);
00104         source->references++;
00105         INSIST(source->references > 0);
00106         UNLOCK(&source->lock);
00107 
00108         *targetp = source;
00109 }
00110 
00111 static void
00112 destroy(isc_counter_t *counter) {
00113         counter->magic = 0;
00114         isc_mutex_destroy(&counter->lock);
00115         isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter));
00116 }
00117 
00118 void
00119 isc_counter_detach(isc_counter_t **counterp) {
00120         isc_counter_t *counter;
00121         isc_boolean_t want_destroy = ISC_FALSE;
00122 
00123         REQUIRE(counterp != NULL && *counterp != NULL);
00124         counter = *counterp;
00125         REQUIRE(VALID_COUNTER(counter));
00126 
00127         *counterp = NULL;
00128 
00129         LOCK(&counter->lock);
00130         INSIST(counter->references > 0);
00131         counter->references--;
00132         if (counter->references == 0)
00133                 want_destroy = ISC_TRUE;
00134         UNLOCK(&counter->lock);
00135 
00136         if (want_destroy)
00137                 destroy(counter);
00138 }

Generated on Tue Apr 28 17:41:03 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha