00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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 }