Statistics
| Branch: | Revision:

grapes / src / PeerSampler / ncast.c @ 480df8da

History | View | Annotate | Download (5.48 KB)

1
/*
2
 *  Copyright (c) 2010 Luca Abeni
3
 *
4
 *  This is free software; see lgpl-2.1.txt
5
 */
6

    
7
#include <sys/time.h>
8
#include <time.h>
9
#include <stdlib.h>
10
#include <stdint.h>
11
#include <stdio.h>
12
#include <stdbool.h>
13
#include <string.h>
14

    
15
#include "net_helper.h"
16
#include "peersampler_iface.h"
17
#include "../Cache/topocache.h"
18
#include "../Cache/ncast_proto.h"
19
#include "../Cache/proto.h"
20
#include "config.h"
21
#include "grapes_msg_types.h"
22

    
23
#define BOOTSTRAP_CYCLES 5
24
#define DEFAULT_CACHE_SIZE 10
25
#define DEFAULT_MAX_TIMESTAMP 5
26

    
27
struct peersampler_context{
28
  uint64_t currtime;
29
  int cache_size;
30
  struct peer_cache *local_cache;
31
  bool bootstrap;
32
  int bootstrap_period;
33
  int period;
34
  int counter;
35
  struct ncast_proto_context *tc;
36
  const struct nodeID **r;
37
};
38

    
39
static uint64_t gettime(void)
40
{
41
  struct timeval tv;
42

    
43
  gettimeofday(&tv, NULL);
44

    
45
  return tv.tv_usec + tv.tv_sec * 1000000ull;
46
}
47

    
48
static struct peersampler_context* ncast_context_init(void)
49
{
50
  struct peersampler_context* con;
51
  con = (struct peersampler_context*) calloc(1,sizeof(struct peersampler_context));
52

    
53
  //Initialize context with default values
54
  con->bootstrap = true;
55
  con->bootstrap_period = 2000000;
56
  con->period = 10000000;
57
  con->currtime = gettime();
58
  con->r = NULL;
59

    
60
  return con;
61
}
62

    
63
static int time_to_send(struct peersampler_context *context)
64
{
65
  int p = context->bootstrap ? context->bootstrap_period : context->period;
66
  if (gettime() - context->currtime > p) {
67
    context->currtime += p;
68

    
69
    return 1;
70
  }
71

    
72
  return 0;
73
}
74

    
75
/*
76
 * Exported Functions!
77
 */
78
static struct peersampler_context* ncast_init(struct nodeID *myID, const void *metadata, int metadata_size, const char *config)
79
{
80
  struct tag *cfg_tags;
81
  struct peersampler_context *context;
82
  int res, max_timestamp;
83

    
84
  context = ncast_context_init();
85
  if (!context) return NULL;
86

    
87
  cfg_tags = config_parse(config);
88
  res = config_value_int(cfg_tags, "cache_size", &context->cache_size);
89
  if (!res) {
90
    context->cache_size = DEFAULT_CACHE_SIZE;
91
  }
92
  res = config_value_int(cfg_tags, "max_timestamp", &max_timestamp);
93
  if (!res) {
94
    max_timestamp = DEFAULT_MAX_TIMESTAMP;
95
  }
96
  free(cfg_tags);
97
  
98
  context->local_cache = cache_init(context->cache_size, metadata_size, max_timestamp);
99
  if (context->local_cache == NULL) {
100
    free(context);
101
    return NULL;
102
  }
103

    
104
  context->tc = ncast_proto_init(myID, metadata, metadata_size);
105
  if (!context->tc){
106
    free(context->local_cache);
107
    free(context);
108
    return NULL;
109
  }
110

    
111
  return context;
112
}
113

    
114
static int ncast_change_metadata(struct peersampler_context *context, const void *metadata, int metadata_size)
115
{
116
  if (ncast_proto_metadata_update(context->tc, metadata, metadata_size) <= 0) {
117
    return -1;
118
  }
119

    
120
  return 1;
121
}
122

    
123
static int ncast_add_neighbour(struct peersampler_context *context, struct nodeID *neighbour, const void *metadata, int metadata_size)
124
{
125
  if (cache_add(context->local_cache, neighbour, metadata, metadata_size) < 0) {
126
    return -1;
127
  }
128
  return ncast_query_peer(context->tc, context->local_cache, neighbour);
129
}
130

    
131
static int ncast_parse_data(struct peersampler_context *context, const uint8_t *buff, int len)
132
{
133
  int dummy;
134

    
135
  if (len) {
136
    const struct topo_header *h = (const struct topo_header *)buff;
137
    struct peer_cache *new, *remote_cache;
138

    
139
    if (h->protocol != MSG_TYPE_TOPOLOGY) {
140
      fprintf(stderr, "NCAST: Wrong protocol!\n");
141

    
142
      return -1;
143
    }
144

    
145
    context->counter++;
146
    if (context->counter == BOOTSTRAP_CYCLES) context->bootstrap = false;
147

    
148
    remote_cache = entries_undump(buff + sizeof(struct topo_header), len - sizeof(struct topo_header));
149
    if (h->type == NCAST_QUERY) {
150
      ncast_reply(context->tc, remote_cache, context->local_cache);
151
    }
152
    new = merge_caches(context->local_cache, remote_cache, context->cache_size, &dummy);
153
    cache_free(remote_cache);
154
    if (new != NULL) {
155
      cache_free(context->local_cache);
156
      context->local_cache = new;
157
    }
158
  }
159

    
160
  if (time_to_send(context)) {
161
    cache_update(context->local_cache);
162
    return ncast_query(context->tc, context->local_cache);
163
  }
164

    
165
  return 0;
166
}
167

    
168
static const struct nodeID **ncast_get_neighbourhood(struct peersampler_context *context, int *n)
169
{
170
  context->r = realloc(context->r, context->cache_size * sizeof(struct nodeID *));
171
  if (context->r == NULL) {
172
    return NULL;
173
  }
174

    
175
  for (*n = 0; nodeid(context->local_cache, *n) && (*n < context->cache_size); (*n)++) {
176
    context->r[*n] = nodeid(context->local_cache, *n);
177
    //fprintf(stderr, "Checking table[%d]\n", *n);
178
  }
179

    
180
  return context->r;
181
}
182

    
183
static const void *ncast_get_metadata(struct peersampler_context *context, int *metadata_size)
184
{
185
  return get_metadata(context->local_cache, metadata_size);
186
}
187

    
188
static int ncast_grow_neighbourhood(struct peersampler_context *context, int n)
189
{
190
  context->cache_size += n;
191

    
192
  return context->cache_size;
193
}
194

    
195
static int ncast_shrink_neighbourhood(struct peersampler_context *context, int n)
196
{
197
  if (context->cache_size < n) {
198
    return -1;
199
  }
200
  context->cache_size -= n;
201

    
202
  return context->cache_size;
203
}
204

    
205
static int ncast_remove_neighbour(struct peersampler_context *context, const struct nodeID *neighbour)
206
{
207
  return cache_del(context->local_cache, neighbour);
208
}
209

    
210
struct peersampler_iface ncast = {
211
  .init = ncast_init,
212
  .change_metadata = ncast_change_metadata,
213
  .add_neighbour = ncast_add_neighbour,
214
  .parse_data = ncast_parse_data,
215
  .get_neighbourhood = ncast_get_neighbourhood,
216
  .get_metadata = ncast_get_metadata,
217
  .grow_neighbourhood = ncast_grow_neighbourhood,
218
  .shrink_neighbourhood = ncast_shrink_neighbourhood,
219
  .remove_neighbour = ncast_remove_neighbour,
220
};