Statistics
| Branch: | Revision:

grapes / src / PeerSampler / ncast.c @ f08e1d8c

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