Added SILC Rand API, SILC Global Variables API and silcruntime.h.in
[runtime.git] / lib / silcutil / silcglobal.c
1 /*
2
3   silcglobal.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silcruntime.h"
21
22 /****************************** Global Storage ******************************/
23
24 /* Set global variable */
25
26 void *silc_global_set_var(const char *name, SilcUInt32 variable_size,
27                           void *initial_value, SilcBool in_tls)
28 {
29   SilcTls tls = silc_thread_get_tls();
30   SilcBool ret;
31   char *var_name;
32   void *var;
33
34   SILC_LOG_DEBUG(("Adding %s variable '%s' of %d bytes",
35                   in_tls ? "Tls" : "global", name, variable_size));
36
37   if (!variable_size) {
38     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
39     return NULL;
40   }
41
42   if (!tls) {
43     /* Initialize Tls for this thread */
44     tls = silc_thread_tls_init();
45     if (!tls)
46       return NULL;
47   }
48
49   if (!in_tls) {
50     if (!tls->variables) {
51       tls->variables = silc_hash_table_alloc(NULL, 0,
52                                              silc_hash_string, NULL,
53                                              silc_hash_string_compare, NULL,
54                                              silc_hash_destructor, NULL,
55                                              TRUE);
56       if (!tls->variables)
57         return NULL;
58     }
59   } else {
60     if (!tls->tls_variables) {
61       tls->tls_variables = silc_hash_table_alloc(NULL, 0,
62                                                  silc_hash_string, NULL,
63                                                  silc_hash_string_compare, NULL,
64                                                  silc_hash_destructor, NULL,
65                                                  TRUE);
66       if (!tls->tls_variables)
67         return NULL;
68     }
69   }
70
71   /* Allocate the variable */
72   var = silc_malloc(variable_size);
73   if (!var)
74     return NULL;
75
76   /* Initialize the variable */
77   if (initial_value)
78     memcpy(var, initial_value, variable_size);
79   else
80     memset(var, 0, variable_size);
81
82   var_name = silc_strdup(name);
83   if (!var_name) {
84     silc_free(var);
85     return NULL;
86   }
87
88   /* Add the variable */
89   if (!in_tls) {
90     silc_mutex_lock(tls->lock);
91     ret = silc_hash_table_set(tls->variables, var_name, var);
92     silc_mutex_unlock(tls->lock);
93   } else {
94     ret = silc_hash_table_set(tls->tls_variables, var_name, var);
95   }
96
97   if (!ret) {
98     silc_free(var);
99     silc_free(var_name);
100     var = NULL;
101   }
102
103   return var;
104 }
105
106 /* Get global variable */
107
108 void *silc_global_get_var(const char *name, SilcBool in_tls)
109 {
110   SilcTls tls = silc_thread_get_tls();
111   void *variable;
112   SilcBool ret;
113
114   SILC_LOG_DEBUG(("Find %s variable named '%s'", in_tls ? "Tls" : "global",
115                   name));
116
117   if (!tls) {
118     silc_set_errno(SILC_ERR_NOT_FOUND);
119     return NULL;
120   }
121
122   if (!in_tls && !tls->variables) {
123     silc_set_errno(SILC_ERR_NOT_FOUND);
124     return NULL;
125   }
126
127   if (in_tls && !tls->tls_variables) {
128     silc_set_errno(SILC_ERR_NOT_FOUND);
129     return NULL;
130   }
131
132   if (!in_tls) {
133     silc_mutex_lock(tls->lock);
134     ret = silc_hash_table_find(tls->variables, (void *)name, NULL, &variable);
135     silc_mutex_unlock(tls->lock);
136   } else {
137     ret = silc_hash_table_find(tls->tls_variables, (void *)name, NULL,
138                                &variable);
139   }
140
141   if (!ret)
142     return NULL;
143
144   return variable;
145 }
146
147 /* Delete global variable */
148
149 SilcBool silc_global_del_var(const char *name, SilcBool in_tls)
150 {
151   SilcTls tls = silc_thread_get_tls();
152
153   SILC_LOG_DEBUG(("Delete %s variable '%s'", in_tls ? "Tls" : "global", name));
154
155   if (!tls) {
156     silc_set_errno(SILC_ERR_NOT_FOUND);
157     return FALSE;
158   }
159
160   if (!in_tls && !tls->variables) {
161     silc_set_errno(SILC_ERR_NOT_FOUND);
162     return FALSE;
163   }
164
165   if (in_tls && !tls->tls_variables) {
166     silc_set_errno(SILC_ERR_NOT_FOUND);
167     return FALSE;
168   }
169
170   return silc_hash_table_del(in_tls ? tls->tls_variables : tls->variables,
171                              (void *)name);
172 }