2 This file is part of GNUnet.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file rps/gnunet-service-rps_view.c
21 * @brief wrapper around the "local view"
22 * @author Julius Bünger
25 #include "gnunet_util_lib.h"
26 #include "gnunet-service-rps_view.h"
32 * Array containing the peers
34 struct GNUNET_PeerIdentity *array;
37 * (Maximum) length of the view
42 * Multipeermap containing the peers
44 struct GNUNET_CONTAINER_MultiPeerMap *mpm;
49 * Create an empty view.
51 * @param len the maximum length for the view
52 * @return The newly created view
55 View_create (uint32_t len)
59 view = GNUNET_new (struct View);
61 view->array = GNUNET_new_array (len, struct GNUNET_PeerIdentity);
63 GNUNET_CONTAINER_multipeermap_create (len, GNUNET_NO); /* might even be
70 * Change length of view
72 * If size is decreased, peers with higher indices are removed.
74 * @param view The view that is changed
75 * @param len the (maximum) length for the view
78 View_change_len (struct View *view,
84 if (GNUNET_CONTAINER_multipeermap_size (view->mpm) < len)
86 /* We might simply clear and free the left over space */
87 GNUNET_array_grow (view->array, view->length, len);
89 else /* We have to remove elements */
91 /* TODO find a way to preserve indices */
92 for (i = 0; i < len; i++)
94 index = GNUNET_CONTAINER_multipeermap_get (view->mpm, &view->array[i]);
95 GNUNET_assert (NULL != index);
98 GNUNET_array_grow (view->array, view->length, len);
99 GNUNET_CONTAINER_multipeermap_destroy (view->mpm);
100 view->mpm = GNUNET_CONTAINER_multipeermap_create (len, GNUNET_NO);
101 for (i = 0; i < len; i++)
103 index = GNUNET_new (uint32_t);
105 GNUNET_CONTAINER_multipeermap_put (view->mpm, &view->array[i], index,
106 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
109 GNUNET_assert (view->length == len);
114 * Get the view as an array
116 * @param view The view of which the array representation is of interest
117 * @return the view in array representation
119 const struct GNUNET_PeerIdentity *
120 View_get_as_array (const struct View *view)
127 * Get the size of the view
129 * @param view The view of which the size should be returned
130 * @return current number of actually contained peers
133 View_size (const struct View *view)
135 return GNUNET_CONTAINER_multipeermap_size (view->mpm);
140 * Insert peer into the view
142 * @param view The view to put the peer into
143 * @param peer the peer to insert
145 * @return GNUNET_OK if peer was actually inserted
146 * GNUNET_NO if peer was not inserted
149 View_put (struct View *view,
150 const struct GNUNET_PeerIdentity *peer)
154 if ((view->length <= View_size (view)) || /* If array is 'full' */
155 (GNUNET_YES == View_contains_peer (view, peer)))
161 index = GNUNET_new (uint32_t);
162 *index = (uint32_t) View_size (view);
163 view->array[*index] = *peer;
164 GNUNET_CONTAINER_multipeermap_put (view->mpm, peer, index,
165 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
172 * Check whether view contains a peer
174 * @param view The which is checked for a peer
175 * @param peer the peer to check for
177 * @return GNUNET_OK if view contains peer
178 * GNUNET_NO otherwise
181 View_contains_peer (const struct View *view,
182 const struct GNUNET_PeerIdentity *peer)
184 return GNUNET_CONTAINER_multipeermap_contains (view->mpm, peer);
189 * Remove peer from view
191 * @param view The view of which to remove the peer
192 * @param peer the peer to remove
194 * @return GNUNET_OK if view contained peer and removed it successfully
195 * GNUNET_NO if view does not contain peer
198 View_remove_peer (struct View *view,
199 const struct GNUNET_PeerIdentity *peer)
202 uint32_t *swap_index;
205 if (GNUNET_NO == View_contains_peer (view, peer))
209 index = GNUNET_CONTAINER_multipeermap_get (view->mpm, peer);
210 GNUNET_assert (NULL != index);
211 last_index = View_size (view) - 1;
212 if (*index < last_index)
213 { /* Fill the 'gap' in the array with the last peer */
214 view->array[*index] = view->array[last_index];
215 GNUNET_assert (GNUNET_YES == View_contains_peer (view,
216 &view->array[last_index]));
217 swap_index = GNUNET_CONTAINER_multipeermap_get (view->mpm,
218 &view->array[last_index]);
219 GNUNET_assert (NULL != swap_index);
220 *swap_index = *index;
223 GNUNET_CONTAINER_multipeermap_remove_all (view->mpm, peer);
229 * Get a peer by index
231 * @param view the view of which to get the peer
232 * @param index the index of the peer to get
234 * @return peer to the corresponding index.
235 * NULL if this index is not known
237 const struct GNUNET_PeerIdentity *
238 View_get_peer_by_index (const struct View *view,
241 if (index < GNUNET_CONTAINER_multipeermap_size (view->mpm))
243 return &view->array[index];
255 * @param view The view to clear
258 View_clear (struct View *view)
260 for (uint32_t i = 0; 0 < View_size (view); i++)
261 { /* Need to free indices stored at peers */
264 GNUNET_assert (GNUNET_YES ==
265 GNUNET_CONTAINER_multipeermap_contains (view->mpm, &view->array[i]));
266 index = GNUNET_CONTAINER_multipeermap_get (view->mpm, &view->array[i]);
267 GNUNET_assert (NULL != index);
269 GNUNET_CONTAINER_multipeermap_remove_all (view->mpm, &view->array[i]);
271 GNUNET_assert (0 == View_size (view));
278 * @param view the view to destroy
281 View_destroy (struct View *view)
284 GNUNET_free (view->array);
286 GNUNET_CONTAINER_multipeermap_destroy (view->mpm);
290 /* end of gnunet-service-rps_view.c */