Statistics
| Branch: | Revision:

grapes / src / PeerSet / peerset_ops.c @ 0c6efcd5

History | View | Annotate | Download (4.92 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
static int nodeid_peer_cmp(const void *id, const void *p)
24
{
25
  const struct peer *peer = *(struct peer *const *)p;
26

    
27
  if(id && p)
28
    return nodeid_cmp( (const struct nodeID *) id, peer->id);
29
  else
30
  {
31
    //fprintf(stderr,"[DEBUG] wrong peer or id\n");
32
    return 0;
33
  }
34
}
35

    
36
static int peerset_check_insert_pos(const struct peerset *h, const struct nodeID *id)
37
{
38
  int a, b, c, r;
39

    
40
  if (! h->n_elements) {
41
    return 0;
42
  }
43

    
44
  a = 0;
45
  b = c = h->n_elements - 1;
46

    
47
  while ((r = nodeid_peer_cmp(id, &h->elements[b])) != 0) {
48
    if (r > 0) {
49
      if (b == c) {
50
        return b + 1;
51
      } else {
52
        a = b + 1;
53
      }
54
    } else {
55
      if (b == a) {
56
        return b;
57
      } else {
58
        c = b;
59
      }
60
    }
61
    b = (a + c) / 2;
62
  }
63

    
64
  return -1;
65
}
66

    
67

    
68
struct peerset *peerset_init(const char *config)
69
{
70
  struct peerset *p;
71
  struct tag *cfg_tags;
72
  int res;
73

    
74
  p = malloc(sizeof(struct peerset));
75
  if (p == NULL) {
76
    return NULL;
77
  }
78
  p->n_elements = 0;
79
  cfg_tags = grapes_config_parse(config);
80
  if (!cfg_tags) {
81
    free(p);
82
    return NULL;
83
  }
84
  res = grapes_config_value_int(cfg_tags, "size", &p->size);
85
  if (!res) {
86
    p->size = 0;
87
  }
88
  free(cfg_tags);
89
  if (p->size) {
90
    p->elements = malloc(p->size * sizeof(struct peer *));
91
  } else {
92
    p->elements = NULL;
93
  }
94

    
95
  return p;
96
}
97

    
98
void peerset_destroy(struct peerset **h)
99
{
100
        peerset_clear(*h,0);
101
        free(*h);
102
        *h = NULL;
103
}
104

    
105
int peerset_push_peer(struct peerset *h, struct peer *e)
106
{
107
  int pos;
108

    
109
  pos = peerset_check_insert_pos(h, e->id);
110
  if (pos < 0){
111
    return 0;
112
  }
113

    
114
  if (h->n_elements == h->size) {
115
    struct peer **res;
116

    
117
    res = realloc(h->elements, (h->size + DEFAULT_SIZE_INCREMENT) * sizeof(struct peer *));
118
    if (res == NULL) {
119
      return -1;
120
    }
121
    h->size += DEFAULT_SIZE_INCREMENT;
122
    h->elements = res;
123
  }
124

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

    
127
  h->elements[pos] = e;;
128

    
129
  return h->n_elements;
130
}
131

    
132
int peerset_add_peer(struct peerset *h,const  struct nodeID *id)
133
{
134
  struct peer *e;
135
  int pos;
136

    
137
  pos = peerset_check_insert_pos(h, id);
138
  if (pos < 0){
139
    return 0;
140
  }
141

    
142
  if (h->n_elements == h->size) {
143
    struct peer **res;
144

    
145
    res = realloc(h->elements, (h->size + DEFAULT_SIZE_INCREMENT) * sizeof(struct peer *));
146
    if (res == NULL) {
147
      return -1;
148
    }
149
    h->size += DEFAULT_SIZE_INCREMENT;
150
    h->elements = res;
151
  }
152

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

    
155
  e = malloc(sizeof(struct peer));
156
  h->elements[pos] = e;
157
  gettimeofday(&e->creation_timestamp, NULL);
158
  e->id = nodeid_dup(id);
159
  e->metadata = NULL;
160
  e->user_data = NULL;
161

    
162
  return h->n_elements;
163
}
164

    
165
void peerset_add_peers(struct peerset *h, struct nodeID **ids, int n)
166
{
167
  int i;
168

    
169
  for (i = 0; i < n; i++) {
170
    peerset_add_peer(h, ids[i]);
171
  }
172
}
173

    
174
int peerset_size(const struct peerset *h)
175
{
176
  return h->n_elements;
177
}
178

    
179
struct peer **peerset_get_peers(const struct peerset *h)
180
{
181
  return h->elements;
182
}
183

    
184
struct peer *peerset_get_peer(const struct peerset *h, const struct nodeID *id)
185
{
186
  int i = peerset_check(h,id);
187
  return (i<0) ? NULL : h->elements[i];
188
}
189

    
190
struct peer *peerset_pop_peer(struct peerset *h, const struct nodeID *id){
191
  int i = peerset_check(h,id);
192
  if (i >= 0) {
193
    struct peer *e = h->elements[i];
194
    memmove(&h->elements[i], &h->elements[i+1], ((h->n_elements--) - (i+1)) * sizeof(struct peer *));
195

    
196
    return e;
197
  }
198
  return NULL;
199
}
200

    
201
int peerset_remove_peer(struct peerset *h, const struct nodeID *id){
202
  int i = peerset_check(h,id);
203
  if (i >= 0) {
204
    struct peer *e = h->elements[i];
205
    nodeid_free(e->id);
206
    if (e->metadata)
207
            free(e->metadata);
208
    if (e->user_data)
209
            free(e->user_data);
210
    memmove(&h->elements[i], &h->elements[i+1], ((h->n_elements--) - (i+1)) * sizeof(struct peer *));
211
    free(e);
212

    
213
    return i;
214
  }
215
  return -1;
216
}
217

    
218
int peerset_check(const struct peerset *h, const struct nodeID *id)
219
{
220
  struct peer **p;
221

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

    
224
  return p ? p - h->elements : -1;
225
}
226

    
227
void peerset_clear(struct peerset *h, int size)
228
{
229
  int i;
230

    
231
  for (i = 0; i < h->n_elements; i++) {
232
    struct peer *e = h->elements[i];
233
    nodeid_free(e->id);
234
    if (e->metadata)
235
            free(e->metadata);
236
    if (e->user_data)
237
            free(e->user_data);
238
    free(e);
239
  }
240

    
241
  h->n_elements = 0;
242
  h->size = size;
243
  if (h->size)
244
          h->elements = realloc(h->elements, size * sizeof(struct peer *));
245
  else
246
  {
247
          free(h->elements);
248
          h->elements = NULL;
249
  }
250
  if (h->elements == NULL) {
251
    h->size = 0;
252
  }
253
}