Statistics
| Branch: | Revision:

grapes / src / PeerSampler / ncast.c @ fb49d822

History | View | Annotate | Download (6.4 KB)

1 8ab58ec7 Luca Abeni
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *
4
 *  This is free software; see lgpl-2.1.txt
5
 */
6
7 480921a6 Luca Abeni
#include <sys/time.h>
8
#include <time.h>
9
#include <stdlib.h>
10
#include <stdint.h>
11
#include <stdio.h>
12 badadecf CsabaKiraly
#include <stdbool.h>
13 480921a6 Luca Abeni
#include <string.h>
14
15 155319cd Luca Abeni
#include "net_helper.h"
16 a515fd33 Luca
#include "peersampler_iface.h"
17 c7cc13c7 Luca Abeni
#include "../Cache/topocache.h"
18
#include "../Cache/ncast_proto.h"
19
#include "../Cache/proto.h"
20 a1333f46 Luca Abeni
#include "config.h"
21 5941d7a1 Csaba Kiraly
#include "grapes_msg_types.h"
22 480921a6 Luca Abeni
23 a1333f46 Luca Abeni
#define DEFAULT_CACHE_SIZE 10
24 18d83f26 Luca Abeni
#define DEFAULT_MAX_TIMESTAMP 5
25 cc8a901b Csaba Kiraly
#define DEFAULT_BOOTSTRAP_CYCLES 5
26
#define DEFAULT_BOOTSTRAP_PERIOD 2*1000*1000
27
#define DEFAULT_PERIOD 10*1000*1000
28 480921a6 Luca Abeni
29 d83a94fa Andrea Zito
struct peersampler_context{
30
  uint64_t currtime;
31
  int cache_size;
32
  struct peer_cache *local_cache;
33
  bool bootstrap;
34
  int bootstrap_period;
35 cc8a901b Csaba Kiraly
  int bootstrap_cycles;
36 d83a94fa Andrea Zito
  int period;
37
  int counter;
38
  struct ncast_proto_context *tc;
39 46878222 Luca Abeni
  const struct nodeID **r;
40 fb49d822 Csaba Kiraly
  int first_ts;
41 d83a94fa Andrea Zito
};
42 496b4f3c Andrea Zito
43 480921a6 Luca Abeni
static uint64_t gettime(void)
44
{
45
  struct timeval tv;
46
47
  gettimeofday(&tv, NULL);
48
49
  return tv.tv_usec + tv.tv_sec * 1000000ull;
50
}
51
52 babdcc03 Luca Abeni
static struct peersampler_context* ncast_context_init(void)
53
{
54 06113eb4 Andrea Zito
  struct peersampler_context* con;
55
  con = (struct peersampler_context*) calloc(1,sizeof(struct peersampler_context));
56
57
  //Initialize context with default values
58 d83a94fa Andrea Zito
  con->bootstrap = true;
59
  con->currtime = gettime();
60 46878222 Luca Abeni
  con->r = NULL;
61 06113eb4 Andrea Zito
62
  return con;
63
}
64
65 d83a94fa Andrea Zito
static int time_to_send(struct peersampler_context *context)
66 480921a6 Luca Abeni
{
67 d83a94fa Andrea Zito
  int p = context->bootstrap ? context->bootstrap_period : context->period;
68
  if (gettime() - context->currtime > p) {
69
    context->currtime += p;
70 480921a6 Luca Abeni
71
    return 1;
72
  }
73
74
  return 0;
75
}
76
77
/*
78 a515fd33 Luca
 * Exported Functions!
79 480921a6 Luca Abeni
 */
80 15d5934d Luca Abeni
static struct peersampler_context* ncast_init(struct nodeID *myID, const void *metadata, int metadata_size, const char *config)
81 480921a6 Luca Abeni
{
82 a1333f46 Luca Abeni
  struct tag *cfg_tags;
83 d83a94fa Andrea Zito
  struct peersampler_context *context;
84 18d83f26 Luca Abeni
  int res, max_timestamp;
85 a1333f46 Luca Abeni
86 d83a94fa Andrea Zito
  context = ncast_context_init();
87
  if (!context) return NULL;
88 06113eb4 Andrea Zito
89 a1333f46 Luca Abeni
  cfg_tags = config_parse(config);
90 d83a94fa Andrea Zito
  res = config_value_int(cfg_tags, "cache_size", &context->cache_size);
91 a1333f46 Luca Abeni
  if (!res) {
92 d83a94fa Andrea Zito
    context->cache_size = DEFAULT_CACHE_SIZE;
93 a1333f46 Luca Abeni
  }
94 18d83f26 Luca Abeni
  res = config_value_int(cfg_tags, "max_timestamp", &max_timestamp);
95
  if (!res) {
96
    max_timestamp = DEFAULT_MAX_TIMESTAMP;
97
  }
98 cc8a901b Csaba Kiraly
  res = config_value_int(cfg_tags, "period", &context->period);
99
  if (!res) {
100
    context->period = DEFAULT_PERIOD;
101
  }
102
  res = config_value_int(cfg_tags, "bootstrap_period", &context->bootstrap_period);
103
  if (!res) {
104
    context->bootstrap_period = DEFAULT_BOOTSTRAP_PERIOD;
105
  }
106
  res = config_value_int(cfg_tags, "bootstrap_cycles", &context->bootstrap_cycles);
107
  if (!res) {
108
    context->bootstrap_cycles = DEFAULT_BOOTSTRAP_CYCLES;
109
  }
110 a1333f46 Luca Abeni
  free(cfg_tags);
111
  
112 d83a94fa Andrea Zito
  context->local_cache = cache_init(context->cache_size, metadata_size, max_timestamp);
113
  if (context->local_cache == NULL) {
114
    free(context);
115 06113eb4 Andrea Zito
    return NULL;
116 480921a6 Luca Abeni
  }
117
118 d83a94fa Andrea Zito
  context->tc = ncast_proto_init(myID, metadata, metadata_size);
119
  if (!context->tc){
120
    free(context->local_cache);
121
    free(context);
122
    return NULL;
123
  }
124
125 fb49d822 Csaba Kiraly
  context->first_ts = (max_timestamp + 1) / 2;
126
  // increase timestamp for initial message, since that is out of the normal cycle of the bootstrap peer
127
  ncast_proto_myentry_update(context->tc, NULL, context->first_ts, NULL, 0);
128
129 d83a94fa Andrea Zito
  return context;
130 480921a6 Luca Abeni
}
131
132 15d5934d Luca Abeni
static int ncast_change_metadata(struct peersampler_context *context, const void *metadata, int metadata_size)
133 90cea048 Luca
{
134 d83a94fa Andrea Zito
  if (ncast_proto_metadata_update(context->tc, metadata, metadata_size) <= 0) {
135 90cea048 Luca
    return -1;
136
  }
137
138
  return 1;
139
}
140
141 15d5934d Luca Abeni
static int ncast_add_neighbour(struct peersampler_context *context, struct nodeID *neighbour, const void *metadata, int metadata_size)
142 480921a6 Luca Abeni
{
143 d83a94fa Andrea Zito
  if (cache_add(context->local_cache, neighbour, metadata, metadata_size) < 0) {
144 36b460c1 Csaba Kiraly
    return -1;
145
  }
146 d83a94fa Andrea Zito
  return ncast_query_peer(context->tc, context->local_cache, neighbour);
147 480921a6 Luca Abeni
}
148
149 06113eb4 Andrea Zito
static int ncast_parse_data(struct peersampler_context *context, const uint8_t *buff, int len)
150 480921a6 Luca Abeni
{
151 661d190d Luca Abeni
  int dummy;
152
153 480921a6 Luca Abeni
  if (len) {
154 01873987 Luca Abeni
    const struct topo_header *h = (const struct topo_header *)buff;
155 11485577 Luca Abeni
    struct peer_cache *new, *remote_cache;
156 480921a6 Luca Abeni
157 026a7e5d Luca Abeni
    if (h->protocol != MSG_TYPE_TOPOLOGY) {
158 480921a6 Luca Abeni
      fprintf(stderr, "NCAST: Wrong protocol!\n");
159
160
      return -1;
161
    }
162
163 d83a94fa Andrea Zito
    context->counter++;
164 fb49d822 Csaba Kiraly
    if (context->counter == context->bootstrap_cycles) {
165
      context->bootstrap = false;
166
      ncast_proto_myentry_update(context->tc, NULL , - context->first_ts, NULL, 0);  // reset the timestamp of our own ID, we are in normal cycle, we will not disturb the algorithm
167
    }
168 badadecf CsabaKiraly
169 418dafe6 Luca
    remote_cache = entries_undump(buff + sizeof(struct topo_header), len - sizeof(struct topo_header));
170 480921a6 Luca Abeni
    if (h->type == NCAST_QUERY) {
171 d83a94fa Andrea Zito
      ncast_reply(context->tc, remote_cache, context->local_cache);
172 480921a6 Luca Abeni
    }
173 d83a94fa Andrea Zito
    new = merge_caches(context->local_cache, remote_cache, context->cache_size, &dummy);
174 6ee18244 Luca
    cache_free(remote_cache);
175 480921a6 Luca Abeni
    if (new != NULL) {
176 d83a94fa Andrea Zito
      cache_free(context->local_cache);
177
      context->local_cache = new;
178 480921a6 Luca Abeni
    }
179
  }
180
181 d83a94fa Andrea Zito
  if (time_to_send(context)) {
182
    cache_update(context->local_cache);
183 480df8da Luca Abeni
    return ncast_query(context->tc, context->local_cache);
184 480921a6 Luca Abeni
  }
185
186
  return 0;
187
}
188
189 06113eb4 Andrea Zito
static const struct nodeID **ncast_get_neighbourhood(struct peersampler_context *context, int *n)
190 480921a6 Luca Abeni
{
191 46878222 Luca Abeni
  context->r = realloc(context->r, context->cache_size * sizeof(struct nodeID *));
192
  if (context->r == NULL) {
193 3c7f8a0c Luca Abeni
    return NULL;
194
  }
195
196 d83a94fa Andrea Zito
  for (*n = 0; nodeid(context->local_cache, *n) && (*n < context->cache_size); (*n)++) {
197 46878222 Luca Abeni
    context->r[*n] = nodeid(context->local_cache, *n);
198 480921a6 Luca Abeni
    //fprintf(stderr, "Checking table[%d]\n", *n);
199
  }
200 3c7f8a0c Luca Abeni
201 46878222 Luca Abeni
  return context->r;
202 480921a6 Luca Abeni
}
203
204 06113eb4 Andrea Zito
static const void *ncast_get_metadata(struct peersampler_context *context, int *metadata_size)
205 005954ae Luca Abeni
{
206 d83a94fa Andrea Zito
  return get_metadata(context->local_cache, metadata_size);
207 005954ae Luca Abeni
}
208
209 06113eb4 Andrea Zito
static int ncast_grow_neighbourhood(struct peersampler_context *context, int n)
210 480921a6 Luca Abeni
{
211 d83a94fa Andrea Zito
  context->cache_size += n;
212 480921a6 Luca Abeni
213 d83a94fa Andrea Zito
  return context->cache_size;
214 480921a6 Luca Abeni
}
215
216 06113eb4 Andrea Zito
static int ncast_shrink_neighbourhood(struct peersampler_context *context, int n)
217 480921a6 Luca Abeni
{
218 d83a94fa Andrea Zito
  if (context->cache_size < n) {
219 480921a6 Luca Abeni
    return -1;
220
  }
221 d83a94fa Andrea Zito
  context->cache_size -= n;
222 480921a6 Luca Abeni
223 d83a94fa Andrea Zito
  return context->cache_size;
224 480921a6 Luca Abeni
}
225
226 15d5934d Luca Abeni
static int ncast_remove_neighbour(struct peersampler_context *context, const struct nodeID *neighbour)
227 480921a6 Luca Abeni
{
228 d83a94fa Andrea Zito
  return cache_del(context->local_cache, neighbour);
229 480921a6 Luca Abeni
}
230
231 a515fd33 Luca
struct peersampler_iface ncast = {
232
  .init = ncast_init,
233
  .change_metadata = ncast_change_metadata,
234
  .add_neighbour = ncast_add_neighbour,
235
  .parse_data = ncast_parse_data,
236
  .get_neighbourhood = ncast_get_neighbourhood,
237
  .get_metadata = ncast_get_metadata,
238
  .grow_neighbourhood = ncast_grow_neighbourhood,
239
  .shrink_neighbourhood = ncast_shrink_neighbourhood,
240
  .remove_neighbour = ncast_remove_neighbour,
241
};