Multi-ApplicationOnlineProfiling  2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Hash_Tree.c
Go to the documentation of this file.
1 /* ############################ MALP License ############################## */
2 /* # Fri Jan 18 14:00:00 CET 2013 # */
3 /* # Copyright or (C) or Copr. Commissariat a l'Energie Atomique # */
4 /* # # */
5 /* # This software is governed by the CeCILL-C license under French law # */
6 /* # and abiding by the rules of distribution of free software. You can # */
7 /* # use, modify and/ or redistribute the software under the terms of # */
8 /* # the CeCILL-C license as circulated by CEA, CNRS and INRIA at the # */
9 /* # following URL http://www.cecill.info. # */
10 /* # # */
11 /* # The fact that you are presently reading this means that you have # */
12 /* # had knowledge of the CeCILL-C license and that you accept its # */
13 /* # terms. # */
14 /* # # */
15 /* # Authors: # */
16 /* # - BESNARD Jean-Baptiste jean-baptiste.besnard@cea.fr # */
17 /* # # */
18 /* ######################################################################## */
19 #include "Hash_Tree.h"
20 
21 #include "Debug.h"
22 #include "CRC64.h"
23 
24 /*
25  * Hash tree node
26  */
27 
28 void Hash_Tree_node_init(struct Hash_Tree_node *node,
29  struct Hash_Tree_node *parent,
30  void *request,
31  size_t request_size,
32  void *payload,
33  size_t payload_size )
34 {
35  node->parent = parent;
36 
37  Chained_List_init(&node->children, 5, sizeof(struct Hash_Tree_node *) );
38 
39  node->request_size = request_size;
40  node->request_entry = malloc( request_size );
41 
42  if(!node->request_entry)
43  {
44  PERROR("malloc");
45  exit(1);
46  }
47 
48  memcpy( node->request_entry, request, request_size );
49 
50  node->request_entry_key = MALP_Trace_crc64((char*)node->request_entry, request_size);
51 
52  node->payload = malloc( payload_size );
53 
54  if(!node->payload)
55  {
56  PERROR("malloc");
57  exit(1);
58  }
59 
60  memcpy( node->payload, payload, payload_size );
61 }
62 
63 
64 void Hash_Tree_node_release( struct Hash_Tree_node *node )
65 {
66  Chained_List_release(&node->children);
67 
68  free(node->request_entry);
69  free(node->payload);
70 
71  memset(node, 0, sizeof(struct Hash_Tree_node ) );
72 }
73 
74 void __Hash_Tree_node_release( void *node )
75 {
76  Hash_Tree_node_release( (struct Hash_Tree_node *)node );
77 }
78 
79 
80 void Hash_Tree_node_push_child( struct Hash_Tree_node *node,
81  struct Hash_Tree_node *child)
82 {
83  Chained_List_push( &node->children, (void*)&child);
84 }
85 
86 /*
87  * Hash Tree
88  */
89 
90 
91 int Hash_Tree_test_func( void *elem, uint64_t key, void *arg )
92 {
93  struct Hash_Tree_node *node = (struct Hash_Tree_node *)elem;
94 
95  if( key == node->request_entry_key )
96  {
97  if( arg )
98  {
99  if( !memcmp( arg, node->request_entry, node->request_size ) )
100  {
101  return 1;
102  }
103  else
104  {
105  return 0;
106  }
107 
108  }
109  else
110  {
111  return 1;
112  }
113  }
114 
115  return 0;
116 }
117 
118 void Hash_Tree_init( struct Hash_Tree *htr, size_t request_size, size_t payload_size )
119 {
120  Hash_Table_init(&htr->nodes, sizeof(struct Hash_Tree_node_cell),
121  4142, HASH_TREE_NODE_COLL_AVOID );
122 
123  Hash_Table_use_lock( &htr->nodes );
124 
125  htr->payload_size = payload_size;
126  htr->request_size = request_size;
127 
128  htr->node_count = 0;
129  htr->lock = 0;
130 }
131 
132 
133 void Hash_Tree_call_free(void *elem, void *pfree_func)
134 {
135  void (*free_func)(void *) = (void (*)(void *))pfree_func;
136 
137  if( free_func )
138  {
139  (free_func)(elem);
140  }
141 }
142 
143 void Hash_Tree_release( struct Hash_Tree *htr, void (*free_func)(void *) )
144 {
145  if( free_func )
146  Hash_Table_walkthrought_2p( &htr->nodes, free_func, Hash_Tree_call_free );
147 
149  memset( htr, 0, sizeof(struct Hash_Tree) );
150 }
151 
152 int Hash_Tree_elem_exits( struct Hash_Tree *htr, void *request )
153 {
154  uint64_t key = MALP_Trace_crc64((char *)request, htr->request_size);
155  return (Hash_Table_get( &htr->nodes , key , request , Hash_Tree_test_func) != NULL)?1:0;
156 }
157 
158 struct Hash_Tree_node * Hash_Tree_get_elem( struct Hash_Tree *htr, void *request )
159 {
160  uint64_t key = MALP_Trace_crc64((char *)request, htr->request_size);
161  return (struct Hash_Tree_node *)Hash_Table_get( &htr->nodes , key , request , Hash_Tree_test_func);
162 }
163 
164 struct Hash_Tree_node * Hash_Tree_push( struct Hash_Tree *htr, void *parent_request, void *new_request, void *payload )
165 {
166 
167  struct Hash_Tree_node *parent = NULL;
168  struct Hash_Tree_node *elem = NULL;
169 
170  if( parent_request )
171  {
172  parent = Hash_Tree_get_elem( htr, parent_request );
173 
174  /* Could not push as parent does not exist */
175  if( !parent )
176  return NULL;
177  }
178 
179  MALP_Spinlock_lock(&htr->lock);
180 
181  elem = Hash_Tree_get_elem( htr, new_request );
182 
183  if( elem )
184  {
185  if( elem->parent != parent )
186  {
187  printf("Warning changing element parent in Hash_Tree\n");
188  elem->parent = parent;
189  }
190 
191  memcpy(elem->payload, payload, htr->payload_size);
192  MALP_Spinlock_unlock(&htr->lock);
193  return elem;
194  }
195 
196  struct Hash_Tree_node node;
197 
198  uint64_t key = MALP_Trace_crc64((char *)new_request, htr->request_size);
199 
200  Hash_Tree_node_init(&node, parent, new_request, htr->request_size, payload, htr->payload_size );
201 
202  elem = (struct Hash_Tree_node * )Hash_Table_push( &htr->nodes, &node , key );
203 
204  if( parent )
205  Hash_Tree_node_push_child( parent, elem );
206 
207  htr->node_count++;
208 
209  MALP_Spinlock_unlock(&htr->lock);
210 
211  return elem;
212 }
213 
214 
215 void _Hash_Tree_walk_all_nodes_call_handler(void *p_node, void *phandler, void *extra_arg)
216 {
217  struct Hash_Tree_node *node = (struct Hash_Tree_node *)p_node;
218  void (*handler)(void *, void *) = (void (*)(void *, void *)) phandler;
219 
220  if(node)
221  {
222  (handler)(Hash_Tree_node_payload(node), extra_arg);
223  }
224 }
225 
226 
227 void _Hash_Tree_walk_all_nodes(struct Hash_Tree *htr, void (*handler)(void *, void *), void *extra_arg)
228 {
229  Hash_Table_walkthrought_3p( &htr->nodes, (void *)handler, (void *)extra_arg, _Hash_Tree_walk_all_nodes_call_handler );
230 }
231 
232 void _Hash_Tree_walk_topological(struct Hash_Tree *htr, struct Hash_Tree_node *node, void (*handler)(void *, void *), void *extra_arg)
233 {
234  if(!node)
235  return;
236 
237  (handler)(Hash_Tree_node_payload(node), extra_arg);
238 
239  int child_count = Hash_Tree_node_get_child_count( node );
240 
241  int i;
242 
243  for( i = 0 ; i < child_count ; i++ )
244  {
245  struct Hash_Tree_node *child = Hash_Tree_node_get_nth_child( node, i );
246  _Hash_Tree_walk_topological(htr, child, handler, extra_arg);
247  }
248 
249 }
250 
251 
252 void Hash_Tree_walk(struct Hash_Tree *htr, void *starting_point_request, void (*handler)(void *, void *), void *extra_arg)
253 {
254  if( !handler )
255  return;
256 
257 
258  if( starting_point_request == NULL )
259  {
260  _Hash_Tree_walk_all_nodes( htr, handler, extra_arg);
261  }
262  else
263  {
264  struct Hash_Tree_node *starting_node = Hash_Tree_get_elem( htr, starting_point_request);
265  if( starting_node )
266  {
267  _Hash_Tree_walk_topological( htr, starting_node, handler, extra_arg );
268  }
269  }
270 }
struct Hash_Tree_node * Hash_Tree_get_elem(struct Hash_Tree *htr, void *request)
Definition: Hash_Tree.c:158
static uint64_t MALP_Trace_crc64(char *source, uint64_t size)
Computes the hash of a given data.
Definition: CRC64.h:54
static void Hash_Table_use_lock(struct Hash_Table *ht)
Indicates that the hashtable must use a lock for operations (get/push)
Definition: Hash_Table.h:66
void Hash_Tree_node_release(struct Hash_Tree_node *node)
Definition: Hash_Tree.c:64
void Hash_Tree_init(struct Hash_Tree *htr, size_t request_size, size_t payload_size)
Definition: Hash_Tree.c:118
void _Hash_Tree_walk_all_nodes_call_handler(void *p_node, void *phandler, void *extra_arg)
Definition: Hash_Tree.c:215
void Hash_Tree_node_init(struct Hash_Tree_node *node, struct Hash_Tree_node *parent, void *request, size_t request_size, void *payload, size_t payload_size)
Definition: Hash_Tree.c:28
void * Hash_Table_push(struct Hash_Table *ht, void *payload, uint64_t key)
adds an element to a hashtable
Definition: Hash_Table.c:198
static void Chained_List_init(struct Chained_List *list, uint64_t chunk_size, size_t payload_size)
Initializes a Chained_List.
Definition: Chained_List.h:286
struct Hash_Tree_node * Hash_Tree_push(struct Hash_Tree *htr, void *parent_request, void *new_request, void *payload)
Definition: Hash_Tree.c:164
#define PERROR(string)
PERROR macro.
Definition: Debug.h:69
int MALP_Spinlock_unlock(MALP_Spinlock *mutex)
Unlocks the given MALP_Spinlock.
Definition: Spinlock.c:41
void __Hash_Tree_node_release(void *node)
Definition: Hash_Tree.c:74
static void * Chained_List_push(struct Chained_List *list, void *payload)
Adds an element to the list.
Definition: Chained_List.h:312
void Hash_Tree_node_push_child(struct Hash_Tree_node *node, struct Hash_Tree_node *child)
Definition: Hash_Tree.c:80
void Hash_Table_init(struct Hash_Table *ht, size_t sizeof_payload, uint64_t table_size, uint8_t coll_avoid)
Hash_Table initialization.
Definition: Hash_Table.c:40
void Hash_Table_walkthrought_2p(struct Hash_Table *ht, void *second_arg, void(*action)(void *, void *))
Executes a function on every stored elements.
Definition: Hash_Table.c:385
void * Hash_Table_get(struct Hash_Table *ht, uint64_t key, void *extra_arg, int(*test_func)(void *, uint64_t, void *))
retrieves an element from the hashtable
Definition: Hash_Table.c:128
void Hash_Tree_call_free(void *elem, void *pfree_func)
Definition: Hash_Tree.c:133
void Hash_Table_release(struct Hash_Table *ht, void(*free_f)(void *))
Hash_Table release.
Definition: Hash_Table.c:67
int MALP_Spinlock_lock(MALP_Spinlock *mutex)
Locks the given MALP_Spinlock.
Definition: Spinlock.c:29
void _Hash_Tree_walk_topological(struct Hash_Tree *htr, struct Hash_Tree_node *node, void(*handler)(void *, void *), void *extra_arg)
Definition: Hash_Tree.c:232
static void Chained_List_release(struct Chained_List *list)
Clears a Chained_List.
Definition: Chained_List.h:298
int Hash_Tree_test_func(void *elem, uint64_t key, void *arg)
Definition: Hash_Tree.c:91
int Hash_Tree_elem_exits(struct Hash_Tree *htr, void *request)
Definition: Hash_Tree.c:152
void Hash_Tree_walk(struct Hash_Tree *htr, void *starting_point_request, void(*handler)(void *, void *), void *extra_arg)
Definition: Hash_Tree.c:252
void Hash_Table_walkthrought_3p(struct Hash_Table *ht, void *second_arg, void *third_arg, void(*action)(void *, void *, void *))
Executes a function on every stored elements.
Definition: Hash_Table.c:435
void _Hash_Tree_walk_all_nodes(struct Hash_Tree *htr, void(*handler)(void *, void *), void *extra_arg)
Definition: Hash_Tree.c:227
void Hash_Tree_release(struct Hash_Tree *htr, void(*free_func)(void *))
Definition: Hash_Tree.c:143