cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

variable.c
Go to the documentation of this file.
1 /*
2  Copyright 2019 Northern.tech AS
3 
4  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; version 3.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 
19  To the extent this program is licensed as part of the Enterprise
20  versions of CFEngine, the applicable Commercial Open Source License
21  (COSL) may apply to this file if you as a licensee so wish it. See
22  included file COSL.txt.
23 */
24 #include <variable.h>
25 
26 #include <map.h>
27 #include <rlist.h>
28 #include <writer.h>
29 #include <conversion.h> /* DataTypeToString */
30 
31 
32 static void VariableDestroy(Variable *var); /* forward declaration */
33 
34 static void VariableDestroy_untyped(void *var)
35 {
36  VariableDestroy(var);
37 }
38 
39 
40 /**
41  Define "VarMap" hash table.
42  Key: VarRef
43  Value: Variable
44 */
51 
52 
54 {
56 };
57 
59 {
62 };
63 
64 /* DO NOT EXPORT, this is for internal (hash table) use only, and it doesn't
65  * free everything in Variable, in particular it leaves var->ref to be handled
66  * by the Map implementation calling the key-destroy function. */
67 static void VariableDestroy(Variable *var)
68 {
69  if (var)
70  {
71  RvalDestroy(var->rval);
72  StringSetDestroy(var->tags);
73  // Nothing to do for ->promise
74 
75  free(var);
76  }
77 }
78 
80 {
81  VariableTable *table = xmalloc(sizeof(VariableTable));
82 
83  table->vars = VarMapNew();
84 
85  return table;
86 }
87 
89 {
90  if (table)
91  {
92  VarMapDestroy(table->vars);
93  free(table);
94  }
95 }
96 
97 /* NULL return value means variable not found. */
98 Variable *VariableTableGet(const VariableTable *table, const VarRef *ref)
99 {
100  Variable *v = VarMapGet(table->vars, ref);
101 
102  char *ref_s = VarRefToString(ref, true); /* TODO optimise */
103 
104  if (v != NULL)
105  {
107  "VariableTableGet(%s): "
108  "Only iterables (Rlists) are allowed to be NULL",
109  ref_s);
110  }
111 
113  {
114  Buffer *buf = BufferNew();
115  BufferPrintf(buf, "VariableTableGet(%s): %s", ref_s,
116  v ? DataTypeToString(v->type) : "NOT FOUND");
117  if (v != NULL)
118  {
119  char *value_s;
120  BufferAppendString(buf, " => ");
121  if (DataTypeIsIterable(v->type) &&
122  v->rval.item == NULL)
123  {
124  value_s = xstrdup("EMPTY");
125  }
126  else
127  {
128  value_s = RvalToString(v->rval);
129  }
130 
131  BufferAppendString(buf, value_s);
132  free(value_s);
133  }
134 
135  LogDebug(LOG_MOD_VARTABLE, "%s", BufferGet(buf));
136 
137  BufferDestroy(buf);
138  }
139 
140  free(ref_s);
141  return v;
142 }
143 
144 bool VariableTableRemove(VariableTable *table, const VarRef *ref)
145 {
146  return VarMapRemove(table->vars, ref);
147 }
148 
149 static Variable *VariableNew(VarRef *ref, Rval rval, DataType type,
150  StringSet *tags, const Promise *promise)
151 {
152  Variable *var = xmalloc(sizeof(Variable));
153 
154  var->ref = ref;
155  var->rval = rval;
156  var->type = type;
157  if (tags == NULL)
158  {
159  var->tags = StringSetFromString("", ',');
160  }
161  else
162  {
163  var->tags = tags;
164  }
165  var->promise = promise;
166 
167  return var;
168 }
169 
170 bool VariableTablePut(VariableTable *table, const VarRef *ref,
171  const Rval *rval, DataType type,
172  const char *tags, const Promise *promise)
173 {
174  assert(VarRefIsQualified(ref));
175 
176  /* TODO assert there are no CF_NS or '.' in the variable name? */
177 
179  {
180  char *value_s = RvalToString(*rval);
181  LogDebug(LOG_MOD_VARTABLE, "VariableTablePut(%s): %s => %s",
182  ref->lval, DataTypeToString(type),
183  rval->item ? value_s : "EMPTY");
184  free(value_s);
185  }
186 
187  CF_ASSERT(rval != NULL || DataTypeIsIterable(type),
188  "VariableTablePut(): "
189  "Only iterables (Rlists) are allowed to be NULL");
190 
191  Variable *var = VariableNew(VarRefCopy(ref), RvalCopy(*rval), type,
192  StringSetFromString(tags, ','), promise);
193  return VarMapInsert(table->vars, var->ref, var);
194 }
195 
196 bool VariableTableClear(VariableTable *table, const char *ns, const char *scope, const char *lval)
197 {
198  const size_t vars_num = VarMapSize(table->vars);
199 
200  if (!ns && !scope && !lval)
201  {
202  VarMapClear(table->vars);
203  bool has_vars = (vars_num > 0);
204  return has_vars;
205  }
206 
207  /* We can't remove elements from the hash table while we are iterating
208  * over it. So we first store the VarRef pointers on a list. */
209 
210  VarRef **to_remove = xmalloc(vars_num * sizeof(*to_remove));
211  size_t remove_count = 0;
212 
213  {
214  VariableTableIterator *iter = VariableTableIteratorNew(table, ns, scope, lval);
215 
216  for (Variable *v = VariableTableIteratorNext(iter);
217  v != NULL;
218  v = VariableTableIteratorNext(iter))
219  {
220  to_remove[remove_count] = v->ref;
221  remove_count++;
222  }
224  }
225 
226  if (remove_count == 0)
227  {
228  free(to_remove);
229  return false;
230  }
231 
232  size_t removed = 0;
233  for(size_t i = 0; i < remove_count; i++)
234  {
235  if (VariableTableRemove(table, to_remove[i]))
236  {
237  removed++;
238  }
239  }
240 
241  free(to_remove);
242  assert(removed == remove_count);
243  return true;
244 }
245 
246 size_t VariableTableCount(const VariableTable *table, const char *ns, const char *scope, const char *lval)
247 {
248  if (!ns && !scope && !lval)
249  {
250  return VarMapSize(table->vars);
251  }
252 
253  VariableTableIterator *iter = VariableTableIteratorNew(table, ns, scope, lval);
254  size_t count = 0;
255  while (VariableTableIteratorNext(iter))
256  {
257  count++;
258  }
260  return count;
261 }
262 
264 {
266 
267  iter->ref = VarRefCopy(ref);
268  iter->iter = MapIteratorInit(table->vars->impl);
269 
270  return iter;
271 }
272 
273 VariableTableIterator *VariableTableIteratorNew(const VariableTable *table, const char *ns, const char *scope, const char *lval)
274 {
275  VarRef ref = { 0 };
276  ref.ns = (char *)ns;
277  ref.scope = (char *)scope;
278  ref.lval = (char *)lval;
279 
280  return VariableTableIteratorNewFromVarRef(table, &ref);
281 }
282 
284 {
285  MapKeyValue *keyvalue;
286 
287  while ((keyvalue = MapIteratorNext(&iter->iter)) != NULL)
288  {
289  Variable *var = keyvalue->value;
290  const char *key_ns = var->ref->ns ? var->ref->ns : "default";
291 
292  if (iter->ref->ns && strcmp(key_ns, iter->ref->ns) != 0)
293  {
294  continue;
295  }
296 
297  if (iter->ref->scope && strcmp(var->ref->scope, iter->ref->scope) != 0)
298  {
299  continue;
300  }
301 
302  if (iter->ref->lval && strcmp(var->ref->lval, iter->ref->lval) != 0)
303  {
304  continue;
305  }
306 
307  if (iter->ref->num_indices > 0)
308  {
309  if (iter->ref->num_indices > var->ref->num_indices)
310  {
311  continue;
312  }
313 
314  bool match = true;
315  for (size_t i = 0; i < iter->ref->num_indices; i++)
316  {
317  if (strcmp(var->ref->indices[i], iter->ref->indices[i]) != 0)
318  {
319  match = false;
320  break;
321  }
322  }
323 
324  if (!match)
325  {
326  continue;
327  }
328  }
329 
330  return var;
331  }
332 
333  return NULL;
334 }
335 
337 {
338  if (iter)
339  {
340  VarRefDestroy(iter->ref);
341  free(iter);
342  }
343 }
void * xmalloc(size_t size)
Definition: alloc-mini.c:46
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
void BufferDestroy(Buffer *buffer)
Destroys a buffer and frees the memory associated with it.
Definition: buffer.c:72
Buffer * BufferNew(void)
Buffer initialization routine.
Definition: buffer.c:48
char * BufferGet(Buffer *buffer)
This functions allows direct access to the storage inside Buffer.
Definition: buffer.c:239
int BufferPrintf(Buffer *buffer, const char *format,...)
Stores complex data on the buffer.
Definition: buffer.c:348
void BufferAppendString(Buffer *buffer, const char *str)
Definition: buffer.c:246
DataType
Definition: cf3.defs.h:368
void free(void *)
bool DataTypeIsIterable(DataType t)
Definition: conversion.c:757
const char * DataTypeToString(DataType type)
Definition: conversion.c:331
#define NULL
Definition: getopt1.c:56
@ LogDebug
Definition: log.h:34
bool LogModuleEnabled(enum LogModule mod)
Definition: logging.c:527
@ LOG_MOD_VARTABLE
Definition: logging.h:62
MapIterator MapIteratorInit(Map *map)
Definition: map.c:325
MapKeyValue * MapIteratorNext(MapIterator *i)
Definition: map.c:343
#define TYPED_MAP_DECLARE(Prefix, KeyType, ValueType)
Definition: map.h:116
#define TYPED_MAP_DEFINE(Prefix, KeyType, ValueType, hash_fn, equal_fn, destroy_key_fn, destroy_value_fn)
Definition: map.h:134
#define CF_ASSERT(condition,...)
Definition: misc_lib.h:51
char * RvalToString(Rval rval)
Definition: rlist.c:1396
void RvalDestroy(Rval rval)
Definition: rlist.c:940
Rval RvalCopy(Rval rval)
Definition: rlist.c:474
StringSet * StringSetFromString(const char *str, char delimiter)
Definition: set.c:179
void StringSetDestroy(StringSet *set)
Definition: set.c:34
Definition: buffer.h:50
void * value
Definition: map_common.h:36
Definition: cf3.defs.h:614
void * item
Definition: cf3.defs.h:615
Definition: set.h:138
Map * impl
Definition: variable.c:45
char ** indices
char * ns
char * scope
size_t num_indices
char * lval
MapIterator iter
Definition: variable.c:61
VarMap * vars
Definition: variable.c:55
VarRef * ref
Definition: variable.h:33
StringSet * tags
Definition: variable.h:36
const Promise * promise
Definition: variable.h:37
DataType type
Definition: variable.h:35
Rval rval
Definition: variable.h:34
bool VarRefEqual_untyped(const void *a, const void *b)
void VarRefDestroy(VarRef *ref)
bool VarRefIsQualified(const VarRef *ref)
unsigned int VarRefHash_untyped(const void *ref, unsigned int seed)
void VarRefDestroy_untyped(void *ref)
VarRef * VarRefCopy(const VarRef *ref)
char * VarRefToString(const VarRef *ref, bool qualified)
bool VariableTableRemove(VariableTable *table, const VarRef *ref)
Definition: variable.c:144
bool VarMapRemove(const VarMap *map, const VarRef *key)
Definition: variable.c:50
void VarMapClear(VarMap *map)
Definition: variable.c:50
bool VariableTablePut(VariableTable *table, const VarRef *ref, const Rval *rval, DataType type, const char *tags, const Promise *promise)
Definition: variable.c:170
Variable * VariableTableIteratorNext(VariableTableIterator *iter)
Definition: variable.c:283
Variable * VarMapGet(const VarMap *map, const VarRef *key)
Definition: variable.c:50
VariableTableIterator * VariableTableIteratorNew(const VariableTable *table, const char *ns, const char *scope, const char *lval)
Definition: variable.c:273
VarMap * VarMapNew(void)
Definition: variable.c:50
VariableTableIterator * VariableTableIteratorNewFromVarRef(const VariableTable *table, const VarRef *ref)
Definition: variable.c:263
static void VariableDestroy(Variable *var)
Definition: variable.c:67
VariableTable * VariableTableNew(void)
Definition: variable.c:79
void VariableTableIteratorDestroy(VariableTableIterator *iter)
Definition: variable.c:336
void VarMapDestroy(VarMap *map)
Definition: variable.c:50
size_t VarMapSize(const VarMap *map)
Definition: variable.c:50
bool VariableTableClear(VariableTable *table, const char *ns, const char *scope, const char *lval)
Definition: variable.c:196
static Variable * VariableNew(VarRef *ref, Rval rval, DataType type, StringSet *tags, const Promise *promise)
Definition: variable.c:149
size_t VariableTableCount(const VariableTable *table, const char *ns, const char *scope, const char *lval)
Definition: variable.c:246
void VariableTableDestroy(VariableTable *table)
Definition: variable.c:88
static void VariableDestroy_untyped(void *var)
Definition: variable.c:34
bool VarMapInsert(const VarMap *map, VarRef *key, Variable *value)
Definition: variable.c:50
Variable * VariableTableGet(const VariableTable *table, const VarRef *ref)
Definition: variable.c:98