]> arthur.barton.de Git - netdata.git/blob - src/dictionary.c
layout: remove executable from unrelated files
[netdata.git] / src / dictionary.c
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 #include <pthread.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "avl.h"
9 #include "common.h"
10 #include "log.h"
11
12 #include "dictionary.h"
13
14 // ----------------------------------------------------------------------------
15 // name_value index
16
17 static int name_value_iterator(avl *a) { if(a) {}; return 0; }
18
19 static int name_value_compare(void* a, void* b) {
20         if(((NAME_VALUE *)a)->hash < ((NAME_VALUE *)b)->hash) return -1;
21         else if(((NAME_VALUE *)a)->hash > ((NAME_VALUE *)b)->hash) return 1;
22         else return strcmp(((NAME_VALUE *)a)->name, ((NAME_VALUE *)b)->name);
23 }
24
25 #define name_value_index_add(dict, cv) avl_insert(&((dict)->values_index), (avl *)(cv))
26 #define name_value_index_del(dict, cv) avl_remove(&((dict)->values_index), (avl *)(cv))
27
28 static NAME_VALUE *dictionary_name_value_index_find(DICTIONARY *dict, const char *name, uint32_t hash) {
29         NAME_VALUE *result = NULL, tmp;
30         tmp.hash = (hash)?hash:simple_hash(name);
31         tmp.name = (char *)name;
32
33         avl_search(&(dict->values_index), (avl *)&tmp, name_value_iterator, (avl **)&result);
34         return result;
35 }
36
37 // ----------------------------------------------------------------------------
38
39 static NAME_VALUE *dictionary_name_value_create(DICTIONARY *dict, const char *name, void *value, size_t value_len) {
40         debug(D_DICTIONARY, "Creating name value entry for name '%s', value '%s'.", name, value);
41
42         NAME_VALUE *nv = calloc(1, sizeof(NAME_VALUE));
43         if(!nv) {
44                 fatal("Cannot allocate name_value of size %z", sizeof(NAME_VALUE));
45                 exit(1);
46         }
47
48         nv->name = strdup(name);
49         if(!nv->name) fatal("Cannot allocate name_value.name of size %z", strlen(name));
50         nv->hash = simple_hash(nv->name);
51
52         nv->value = malloc(value_len);
53         if(!nv->value) fatal("Cannot allocate name_value.value of size %z", value_len);
54         memcpy(nv->value, value, value_len);
55
56         // link it
57         pthread_rwlock_wrlock(&dict->rwlock);
58         nv->next = dict->values;
59         dict->values = nv;
60         pthread_rwlock_unlock(&dict->rwlock);
61
62         // index it
63         name_value_index_add(dict, nv);
64
65         return nv;
66 }
67
68 static void dictionary_name_value_destroy(DICTIONARY *dict, NAME_VALUE *nv) {
69         debug(D_DICTIONARY, "Destroying name value entry for name '%s'.", nv->name);
70
71         pthread_rwlock_wrlock(&dict->rwlock);
72         if(dict->values == nv) dict->values = nv->next;
73         else {
74                 NAME_VALUE *n = dict->values;
75                 while(n && n->next && n->next != nv) nv = nv->next;
76                 if(!n || n->next != nv) {
77                         fatal("Cannot find name_value with name '%s' in dictionary.", nv->name);
78                         exit(1);
79                 }
80                 n->next = nv->next;
81                 nv->next = NULL;
82         }
83         pthread_rwlock_unlock(&dict->rwlock);
84
85         free(nv->value);
86         free(nv);
87 }
88
89 // ----------------------------------------------------------------------------
90
91 DICTIONARY *dictionary_create(void) {
92         debug(D_DICTIONARY, "Creating dictionary.");
93
94         DICTIONARY *dict = calloc(1, sizeof(DICTIONARY));
95         if(!dict) {
96                 fatal("Cannot allocate DICTIONARY");
97                 exit(1);
98         }
99
100         avl_init(&dict->values_index, name_value_compare);
101         pthread_rwlock_init(&dict->rwlock, NULL);
102
103         return dict;
104 }
105
106 void dictionary_destroy(DICTIONARY *dict) {
107         debug(D_DICTIONARY, "Destroying dictionary.");
108
109         pthread_rwlock_wrlock(&dict->rwlock);
110         while(dict->values) dictionary_name_value_destroy(dict, dict->values);
111         pthread_rwlock_unlock(&dict->rwlock);
112
113         free(dict);
114 }
115
116 // ----------------------------------------------------------------------------
117
118 void *dictionary_set(DICTIONARY *dict, const char *name, void *value, size_t value_len) {
119         debug(D_DICTIONARY, "SET dictionary entry with name '%s'.", name);
120
121         pthread_rwlock_rdlock(&dict->rwlock);
122         NAME_VALUE *nv = dictionary_name_value_index_find(dict, name, 0);
123         pthread_rwlock_unlock(&dict->rwlock);
124         if(!nv) {
125                 debug(D_DICTIONARY, "Dictionary entry with name '%s' not found. Creating a new one.", name);
126                 nv = dictionary_name_value_create(dict, name, value, value_len);
127                 if(!nv) {
128                         fatal("Cannot create name_value.");
129                         exit(1);
130                 }
131                 return nv->value;
132         }
133         else {
134                 debug(D_DICTIONARY, "Dictionary entry with name '%s' found. Changing its value.", name);
135                 pthread_rwlock_wrlock(&dict->rwlock);
136                 void *old = nv->value;
137                 nv->value = malloc(value_len);
138                 if(!nv->value) fatal("Cannot allocate value of size %z", value_len);
139                 memcpy(nv->value, value, value_len);
140                 pthread_rwlock_unlock(&dict->rwlock);
141                 free(old);
142         }
143
144         return nv->value;
145 }
146
147 void *dictionary_get(DICTIONARY *dict, const char *name) {
148         debug(D_DICTIONARY, "GET dictionary entry with name '%s'.", name);
149
150         pthread_rwlock_rdlock(&dict->rwlock);
151         NAME_VALUE *nv = dictionary_name_value_index_find(dict, name, 0);
152         pthread_rwlock_unlock(&dict->rwlock);
153         if(!nv) {
154                 debug(D_DICTIONARY, "Not found dictionary entry with name '%s'.", name);
155                 return NULL;
156         }
157
158         debug(D_DICTIONARY, "Found dictionary entry with name '%s'.", name);
159         return nv->value;
160 }