Statistics
| Branch: | Revision:

grapes / src / PeerSet / peerset_ops.c @ b79c8e3a

History | View | Annotate | Download (5.1 KB)

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

    
8
#include <stdlib.h>
9
#include <stdio.h>
10
#include <stdint.h>
11
#include <string.h>
12
#include <limits.h>
13

    
14
#include "peerset_private.h"
15
#include "peer.h"
16
#include "peerset.h"
17
#include "chunkidset.h"
18
#include "net_helper.h"
19
#include "grapes_config.h"
20

    
21
#define DEFAULT_SIZE_INCREMENT 32
22

    
23
void peer_init_data(struct peer *p)
24
{
25
        if (p)
26
        {
27
                p->metadata = NULL;
28
                p->user_data = NULL;
29
        }
30
}
31

    
32
void peer_deinit_data(struct peer *p)
33
{
34
        if(p && p->metadata)
35
                free(p->metadata);
36
        if(p && p->metadata)
37
                free(p->user_data);
38
}
39

    
40
peer_deinit_f peer_deinit = peer_deinit_data;
41
peer_init_f peer_init = peer_init_data;
42

    
43
static int nodeid_peer_cmp(const void *id, const void *p)
44
{
45
  const struct peer *peer = *(struct peer *const *)p;
46

    
47
  if(id && p)
48
    return nodeid_cmp( (const struct nodeID *) id, peer->id);
49
  else
50
  {
51
    //fprintf(stderr,"[DEBUG] wrong peer or id\n");
52
    return 0;
53
  }
54
}
55

    
56
static int peerset_check_insert_pos(const struct peerset *h, const struct nodeID *id)
57
{
58
  int a, b, c, r;
59

    
60
  if (! h->n_elements) {
61
    return 0;
62
  }
63

    
64
  a = 0;
65
  b = c = h->n_elements - 1;
66

    
67
  while ((r = nodeid_peer_cmp(id, &h->elements[b])) != 0) {
68
    if (r > 0) {
69
      if (b == c) {
70
        return b + 1;
71
      } else {
72
        a = b + 1;
73
      }
74
    } else {
75
      if (b == a) {
76
        return b;
77
      } else {
78
        c = b;
79
      }
80
    }
81
    b = (a + c) / 2;
82
  }
83

    
84
  return -1;
85
}
86

    
87

    
88
struct peerset *peerset_init(const char *config)
89
{
90
  struct peerset *p;
91
  struct tag *cfg_tags;
92
  int res;
93

    
94
  p = malloc(sizeof(struct peerset));
95
  if (p == NULL) {
96
    return NULL;
97
  }
98
  p->n_elements = 0;
99
  cfg_tags = grapes_config_parse(config);
100
  if (!cfg_tags) {
101
    free(p);
102
    return NULL;
103
  }
104
  res = grapes_config_value_int(cfg_tags, "size", &p->size);
105
  if (!res) {
106
    p->size = 0;
107
  }
108
  free(cfg_tags);
109
  if (p->size) {
110
    p->elements = malloc(p->size * sizeof(struct peer *));
111
  } else {
112
    p->elements = NULL;
113
  }
114

    
115
  return p;
116
}
117

    
118
void peerset_destroy(struct peerset **h)
119
{
120
        peerset_clear(*h,0);
121
        free(*h);
122
        *h = NULL;
123
}
124

    
125
int peerset_push_peer(struct peerset *h, struct peer *e)
126
{
127
  int pos;
128

    
129
  pos = peerset_check_insert_pos(h, e->id);
130
  if (pos < 0){
131
    return 0;
132
  }
133

    
134
  if (h->n_elements == h->size) {
135
    struct peer **res;
136

    
137
    res = realloc(h->elements, (h->size + DEFAULT_SIZE_INCREMENT) * sizeof(struct peer *));
138
    if (res == NULL) {
139
      return -1;
140
    }
141
    h->size += DEFAULT_SIZE_INCREMENT;
142
    h->elements = res;
143
  }
144

    
145
  memmove(&h->elements[pos + 1], &h->elements[pos] , ((h->n_elements++) - pos) * sizeof(struct peer *));
146

    
147
  h->elements[pos] = e;;
148

    
149
  return h->n_elements;
150
}
151

    
152
int peerset_add_peer(struct peerset *h,const  struct nodeID *id)
153
{
154
  struct peer *e;
155
  int pos;
156

    
157
  pos = peerset_check_insert_pos(h, id);
158
  if (pos < 0){
159
    return 0;
160
  }
161

    
162
  if (h->n_elements == h->size) {
163
    struct peer **res;
164

    
165
    res = realloc(h->elements, (h->size + DEFAULT_SIZE_INCREMENT) * sizeof(struct peer *));
166
    if (res == NULL) {
167
      return -1;
168
    }
169
    h->size += DEFAULT_SIZE_INCREMENT;
170
    h->elements = res;
171
  }
172

    
173
  memmove(&h->elements[pos + 1], &h->elements[pos] , ((h->n_elements++) - pos) * sizeof(struct peer *));
174

    
175
  e = malloc(sizeof(struct peer));
176
  h->elements[pos] = e;
177
  gettimeofday(&e->creation_timestamp, NULL);
178
  e->id = nodeid_dup(id);
179
  peer_init(e);
180

    
181
  return h->n_elements;
182
}
183

    
184
void peerset_add_peers(struct peerset *h, struct nodeID **ids, int n)
185
{
186
  int i;
187

    
188
  for (i = 0; i < n; i++) {
189
    peerset_add_peer(h, ids[i]);
190
  }
191
}
192

    
193
int peerset_size(const struct peerset *h)
194
{
195
  return h->n_elements;
196
}
197

    
198
struct peer **peerset_get_peers(const struct peerset *h)
199
{
200
  return h->elements;
201
}
202

    
203
struct peer *peerset_get_peer(const struct peerset *h, const struct nodeID *id)
204
{
205
  int i = peerset_check(h,id);
206
  return (i<0) ? NULL : h->elements[i];
207
}
208

    
209
struct peer *peerset_pop_peer(struct peerset *h, const struct nodeID *id){
210
  int i = peerset_check(h,id);
211
  if (i >= 0) {
212
    struct peer *e = h->elements[i];
213
    memmove(&h->elements[i], &h->elements[i+1], ((h->n_elements--) - (i+1)) * sizeof(struct peer *));
214

    
215
    return e;
216
  }
217
  return NULL;
218
}
219

    
220
int peerset_remove_peer(struct peerset *h, const struct nodeID *id){
221
  int i = peerset_check(h,id);
222
  if (i >= 0) {
223
    struct peer *e = h->elements[i];
224
    nodeid_free(e->id);
225
    if (peer_deinit)
226
            peer_deinit(e);
227
    memmove(&h->elements[i], &h->elements[i+1], ((h->n_elements--) - (i+1)) * sizeof(struct peer *));
228
    free(e);
229

    
230
    return i;
231
  }
232
  return -1;
233
}
234

    
235
int peerset_check(const struct peerset *h, const struct nodeID *id)
236
{
237
  struct peer **p;
238

    
239
  p = bsearch(id, h->elements, (size_t) h->n_elements, sizeof(h->elements[0]), nodeid_peer_cmp);
240

    
241
  return p ? p - h->elements : -1;
242
}
243

    
244
void peerset_clear(struct peerset *h, int size)
245
{
246
  int i;
247

    
248
  for (i = 0; i < h->n_elements; i++) {
249
    struct peer *e = h->elements[i];
250
    nodeid_free(e->id);
251
    if (peer_deinit)
252
            peer_deinit(e);
253
    free(e);
254
  }
255

    
256
  h->n_elements = 0;
257
  h->size = size;
258
  if (h->size)
259
          h->elements = realloc(h->elements, size * sizeof(struct peer *));
260
  else
261
  {
262
          free(h->elements);
263
          h->elements = NULL;
264
  }
265
  if (h->elements == NULL) {
266
    h->size = 0;
267
  }
268
}