aboutsummaryrefslogtreecommitdiff
path: root/src/rps/gnunet-service-rps_view.c
diff options
context:
space:
mode:
authorJulius Bünger <buenger@mytum.de>2015-11-29 20:44:44 +0000
committerJulius Bünger <buenger@mytum.de>2015-11-29 20:44:44 +0000
commitd72d8e05401ace44b57432463f136bcfe55cee03 (patch)
tree8d1374ae5ebd8aa7eb7b5be6ee4d88b7fa78c298 /src/rps/gnunet-service-rps_view.c
parenta0e27c0bd09fc4b0d70295baa5d7e052c46fe4ff (diff)
downloadgnunet-d72d8e05401ace44b57432463f136bcfe55cee03.tar.gz
gnunet-d72d8e05401ace44b57432463f136bcfe55cee03.zip
added helper for handling the "view" in rps
Signed-off-by: Julius Bünger <buenger@mytum.de>
Diffstat (limited to 'src/rps/gnunet-service-rps_view.c')
-rw-r--r--src/rps/gnunet-service-rps_view.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/rps/gnunet-service-rps_view.c b/src/rps/gnunet-service-rps_view.c
new file mode 100644
index 000000000..2cf0287bb
--- /dev/null
+++ b/src/rps/gnunet-service-rps_view.c
@@ -0,0 +1,256 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file rps/gnunet-service-rps_view.c
23 * @brief wrapper around the "local view"
24 * @author Julius Bünger
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet-service-rps_view.h"
29#include <inttypes.h>
30
31
32/**
33 * Array containing the peers
34 */
35static struct GNUNET_PeerIdentity *array;
36
37/**
38 * (Maximum) length of the view
39 */
40static uint32_t length;
41
42/**
43 * Multipeermap containing the peers
44 */
45static struct GNUNET_CONTAINER_MultiPeerMap *mpm;
46
47
48/**
49 * Create an empty view.
50 *
51 * @param len the maximum length for the view
52 */
53void
54View_create (uint32_t len)
55{
56 length = len;
57 array = GNUNET_new_array (len, struct GNUNET_PeerIdentity);
58 mpm = GNUNET_CONTAINER_multipeermap_create (len, GNUNET_NO); /* might even be
59 * set to _YES */
60}
61
62/**
63 * Change length of view
64 *
65 * @param len the (maximum) length for the view
66 */
67void
68View_change_len (uint32_t len)
69{
70 uint32_t i;
71 uint32_t *index;
72
73 if (GNUNET_CONTAINER_multipeermap_size (mpm) < len)
74 { /* Simply shrink */
75 /* We might simply clear and free the left over space */
76 GNUNET_array_grow (array, length, len);
77 }
78 else /* We have to remove elements */
79 {
80 /* TODO find a way to preserve indices */
81 for (i = 0; i < len; i++)
82 {
83 index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[i]);
84 GNUNET_assert (NULL != index);
85 GNUNET_free (index);
86 }
87 GNUNET_array_grow (array, length, len);
88 GNUNET_CONTAINER_multipeermap_destroy (mpm);
89 mpm = GNUNET_CONTAINER_multipeermap_create (len, GNUNET_NO);
90 for (i = 0; i < len; i++)
91 {
92 index = GNUNET_new (uint32_t);
93 *index = i;
94 GNUNET_CONTAINER_multipeermap_put (mpm, &array[i], index,
95 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
96 }
97 }
98 GNUNET_assert (length == len);
99}
100
101/**
102 * Get the view as an array
103 *
104 * @return the view in array representation
105 */
106const struct GNUNET_PeerIdentity *
107View_get_as_array ()
108{
109 return array;
110}
111
112/**
113 * Get the size of the view
114 *
115 * @return current number of actually contained peers
116 */
117unsigned int
118View_size ()
119{
120 return GNUNET_CONTAINER_multipeermap_size (mpm);
121}
122
123/**
124 * Insert peer into the view
125 *
126 * @param peer the peer to insert
127 *
128 * @return GNUNET_OK if peer was actually inserted
129 * GNUNET_NO if peer was not inserted
130 */
131int
132View_put (const struct GNUNET_PeerIdentity *peer)
133{
134 uint32_t *index;
135
136 if ((length <= View_size ()) || /* If array is 'full' */
137 (GNUNET_YES == View_contains_peer (peer)))
138 {
139 return GNUNET_NO;
140 }
141 else
142 {
143 index = GNUNET_new (uint32_t);
144 *index = (uint32_t) View_size ();
145 array[*index] = *peer;
146 GNUNET_CONTAINER_multipeermap_put (mpm, peer, index,
147 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
148 return GNUNET_OK;
149 }
150}
151
152/**
153 * Check whether view contains a peer
154 *
155 * @param peer the peer to check for
156 *
157 * @return GNUNET_OK if view contains peer
158 * GNUNET_NO otherwise
159 */
160int
161View_contains_peer (const struct GNUNET_PeerIdentity *peer)
162{
163 return GNUNET_CONTAINER_multipeermap_contains (mpm, peer);
164}
165
166/**
167 * Remove peer from view
168 *
169 * @param peer the peer to remove
170 *
171 * @return GNUNET_OK if view contained peer and removed it successfully
172 * GNUNET_NO if view does not contain peer
173 */
174int
175View_remove_peer (const struct GNUNET_PeerIdentity *peer)
176{
177 uint32_t *index;
178
179 if (GNUNET_YES == View_contains_peer (peer))
180 {
181 index = GNUNET_CONTAINER_multipeermap_get (mpm, peer);
182 GNUNET_assert (NULL != index);
183 if (*index == GNUNET_CONTAINER_multipeermap_size (mpm) - 1)
184 { /* Last peer in array - simply remove */
185 }
186 else
187 { /* Fill the 'gap' in the array with the last peer */
188 array[*index] = array[View_size ()];
189 }
190 GNUNET_CONTAINER_multipeermap_remove_all (mpm, peer);
191 return GNUNET_OK;
192 }
193 else
194 {
195 return GNUNET_NO;
196 }
197}
198
199/**
200 * Get a peer by index
201 *
202 * @param index the index of the peer to get
203 *
204 * @return peer to the corresponding index.
205 * NULL if this index is not known
206 */
207const struct GNUNET_PeerIdentity *
208View_get_peer_by_index (uint32_t index)
209{
210 if (index < GNUNET_CONTAINER_multipeermap_size (mpm))
211 {
212 return &array[index];
213 }
214 else
215 {
216 return NULL;
217 }
218}
219
220/**
221 * Clear the custom peer map
222 *
223 * @param c_peer_map the custom peer map to look in
224 *
225 * @return size of the map
226 */
227void
228View_clear ()
229{
230 uint32_t i;
231 uint32_t *index;
232
233 for (i = 0; i < GNUNET_CONTAINER_multipeermap_size (mpm); i++)
234 { /* Need to free indices stored at peers */
235 index = GNUNET_CONTAINER_multipeermap_get (mpm, &array[i]);
236 GNUNET_assert (NULL != index);
237 GNUNET_free (index);
238 GNUNET_CONTAINER_multipeermap_remove_all (mpm, &array[i]);
239 }
240 GNUNET_assert (0 == GNUNET_CONTAINER_multipeermap_size (mpm));
241}
242
243/**
244 * Destroy peermap.
245 *
246 * @param c_peer_map the map to destroy
247 */
248void
249View_destroy ()
250{
251 View_clear ();
252 GNUNET_free (array);
253 GNUNET_CONTAINER_multipeermap_destroy (mpm);
254}
255
256/* end of gnunet-service-rps_view.c */