summaryrefslogtreecommitdiffstats
path: root/runtime/map.h
blob: 9e30a9269ea8ab0084736eefda3500d84b38e27b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#ifndef _MAP_H_
#define _MAP_H_
/* -*- linux-c -*- */

/** @file map.h
 * @brief Header file for maps and lists 
 */
/** @addtogroup maps 
 * @{ 
 */

#include <linux/types.h>

/** Statistics are stored in this struct */
typedef struct {
	int64_t count;
	int64_t sum;
	int64_t min, max;
	int64_t histogram[BUCKETS];
} stat;

/** Keys are either longs or char * */
union key_data {
	long val;
	char *str;
};

/** keys can be longs or strings */
enum keytype { NONE, LONG, STR } __attribute__ ((packed));
/** values can be either int64, stats or strings */
enum valtype { INT64, STAT, STRING, END };


/** basic map element */
struct map_node {
	/** list of other nodes in the map */
	struct list_head lnode;
	/** list of nodes with the same hash value */
	struct hlist_node hnode; 
	union key_data key1;
	union key_data key2;
	enum keytype key1type;
	enum keytype key2type;
};

/** map element containing int64 */
struct map_node_int64 {
	struct map_node n;
	int64_t val;
};

/** map element containing string */
struct map_node_str {
	struct map_node n;
	char *str;
};

/** map element containing stats */
struct map_node_stat {
	struct map_node n;
	stat stats;
};

/** This structure contains all information about a map.
 * It is allocated once when _stp_map_new() is called. 
 */
struct map_root {
	/** type of the values stored in the array */
	enum valtype type;
	
 	/** maximum number of elements allowed in the array. */
	int maxnum;

	/** current number of used elements */
	int num;

	/** when more than maxnum elements, wrap or discard? */
	int no_wrap;

	/** linked list of current entries */
	struct list_head head;

	/** pool of unused entries.  Used only when entries are statically allocated
	    at startup. */
	struct list_head pool;

	/** saved key entry for lookups */
	struct map_node *key;

	/** this is the creation data saved between the key functions and the
	    set/get functions 
	    @todo Needs to be per-cpu data for SMP support */
	u_int8_t create;
	enum keytype c_key1type;
	enum keytype c_key2type;
	struct hlist_head *c_keyhead;
	union key_data c_key1;
	union key_data c_key2;

	/** the hash table for this array */
	struct hlist_head hashes[HASH_TABLE_SIZE];

	/** pointer to allocated memory space. Used for freeing memory. */
	void *membuf;
};

/** All maps are of this type. */
typedef struct map_root *MAP;

/** Extracts string from key1 union */
#define key1str(ptr) (ptr->n.key1.str)
/** Extracts string from key2 union */
#define key2str(ptr) (ptr->n.key2.str)
/** Extracts int from key1 union */
#define key1int(ptr) (ptr->n.key1.val)
/** Extracts int from key2 union */
#define key2int(ptr) (ptr->n.key2.val)

/** Macro to call the proper _stp_map_key functions based on the
 * types of the arguments. 
 * @note May cause compiler warning on some GCCs 
 */
#define _stp_map_key2(map, key1, key2)				\
  ({								\
    if (__builtin_types_compatible_p (typeof (key1), char[]))	\
      if (__builtin_types_compatible_p (typeof (key2), char[])) \
	_stp_map_key_str_str (map, (char *)(key1), (char *)(key2));	\
      else							\
	_stp_map_key_str_long (map, (char *)(key1), (long)(key2));	\
    else							\
      if (__builtin_types_compatible_p (typeof (key2), char[])) \
	_stp_map_key_long_str (map, (long)(key1), (char *)(key2));	\
      else							\
	_stp_map_key_long_long (map, (long)(key1), (long)(key2));	\
  })

/** Macro to call the proper _stp_map_key function based on the
 * type of the argument. 
 * @note May cause compiler warning on some GCCs 
 */
#define _stp_map_key(map, key)				\
  ({								\
    if (__builtin_types_compatible_p (typeof (key), char[]))	\
      _stp_map_key_str (map, (char *)(key));				\
    else							\
      _stp_map_key_long (map, (long)(key));				\
  })

/** Macro to call the proper _stp_map_set function based on the
 * type of the argument. 
 * @note May cause compiler warning on some GCCs 
 */
#define _stp_map_set(map, val)				\
  ({								\
    if (__builtin_types_compatible_p (typeof (val), char[]))	\
      _stp_map_set_str (map, (char *)(val));				\
    else							\
      _stp_map_set_int64 (map, (int64_t)(val));			\
  })

/** Loop through all elements of a map or list.
 * @param map 
 * @param ptr pointer to a map_node_stat, map_node_int64 or map_node_str
 *
 * @b Example:
 * @include foreach.c
 */

#define foreach(map, ptr)				\
  for (ptr = (typeof(ptr))_stp_map_start(map); ptr; \
       ptr = (typeof(ptr))_stp_map_iter (map, (struct map_node *)ptr))

/** @} */

/** @ingroup lists
 * @brief Macro to call the proper _stp_list_add function based on the
 * types of the argument. 
 *
 * @note May cause compiler warning on some GCCs 
 */
#define _stp_list_add(map, val)				\
  ({								\
    if (__builtin_types_compatible_p (typeof (val), char[]))	\
      _stp_list_add_str (map, (char *)(val));				\
    else							\
      _stp_list_add_int64 (map, (int64_t)(val));			\
  })

#endif /* _MAP_H_ */