Statistics
| Branch: | Revision:

grapes / src / PeerSet / peerset_ops.c @ 176b8de8

History | View | Annotate | Download (4.68 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 <stdint.h>
10
#include <string.h>
11
#include <limits.h>
12

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

    
20
#define DEFAULT_SIZE_INCREMENT 32
21

    
22
static int nodeid_peer_cmp(const void *id, const void *p)
23
{
24
  const struct peer *peer = *(struct peer *const *)p;
25

    
26
  return nodeid_cmp( (const struct nodeID *) id, peer->id);
27
}
28

    
29
static int peerset_check_insert_pos(const struct peerset *h, const struct nodeID *id)
30
{
31
  int a, b, c, r;
32

    
33
  if (! h->n_elements) {
34
    return 0;
35
  }
36

    
37
  a = 0;
38
  b = c = h->n_elements - 1;
39

    
40
  while ((r = nodeid_peer_cmp(id, &h->elements[b])) != 0) {
41
    if (r > 0) {
42
      if (b == c) {
43
        return b + 1;
44
      } else {
45
        a = b + 1;
46
      }
47
    } else {
48
      if (b == a) {
49
        return b;
50
      } else {
51
        c = b;
52
      }
53
    }
54
    b = (a + c) / 2;
55
  }
56

    
57
  return -1;
58
}
59

    
60

    
61
struct peerset *peerset_init(const char *config)
62
{
63
  struct peerset *p;
64
  struct tag *cfg_tags;
65
  int res;
66

    
67
  p = malloc(sizeof(struct peerset));
68
  if (p == NULL) {
69
    return NULL;
70
  }
71
  p->n_elements = 0;
72
  cfg_tags = grapes_config_parse(config);
73
  if (!cfg_tags) {
74
    free(p);
75
    return NULL;
76
  }
77
  res = grapes_config_value_int(cfg_tags, "size", &p->size);
78
  if (!res) {
79
    p->size = 0;
80
  }
81
  free(cfg_tags);
82
  if (p->size) {
83
    p->elements = malloc(p->size * sizeof(struct peer *));
84
  } else {
85
    p->elements = NULL;
86
  }
87

    
88
  return p;
89
}
90

    
91
void peerset_destroy(struct peerset **h)
92
{
93
        peerset_clear(*h,0);
94
        free(*h);
95
        *h = NULL;
96
}
97

    
98
int peerset_push_peer(struct peerset *h,const  struct peer *e)
99
{
100
  int pos;
101

    
102
  pos = peerset_check_insert_pos(h, e->id);
103
  if (pos < 0){
104
    return 0;
105
  }
106

    
107
  if (h->n_elements == h->size) {
108
    struct peer **res;
109

    
110
    res = realloc(h->elements, (h->size + DEFAULT_SIZE_INCREMENT) * sizeof(struct peer *));
111
    if (res == NULL) {
112
      return -1;
113
    }
114
    h->size += DEFAULT_SIZE_INCREMENT;
115
    h->elements = res;
116
  }
117

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

    
120
  h->elements[pos] = e;;
121

    
122
  return h->n_elements;
123
}
124

    
125
int peerset_add_peer(struct peerset *h,const  struct nodeID *id)
126
{
127
  struct peer *e;
128
  int pos;
129

    
130
  pos = peerset_check_insert_pos(h, id);
131
  if (pos < 0){
132
    return 0;
133
  }
134

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

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

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

    
148
  e = malloc(sizeof(struct peer));
149
  h->elements[pos] = e;;
150
  e->id = nodeid_dup(id);
151
  gettimeofday(&e->creation_timestamp,NULL);
152
  e->bmap = chunkID_set_init("type=bitmap");
153
  timerclear(&e->bmap_timestamp);
154
  e->cb_size = 0;
155
  e->capacity = 0;
156

    
157
  return h->n_elements;
158
}
159

    
160
void peerset_add_peers(struct peerset *h, struct nodeID **ids, int n)
161
{
162
  int i;
163

    
164
  for (i = 0; i < n; i++) {
165
    peerset_add_peer(h, ids[i]);
166
  }
167
}
168

    
169
int peerset_size(const struct peerset *h)
170
{
171
  return h->n_elements;
172
}
173

    
174
struct peer **peerset_get_peers(const struct peerset *h)
175
{
176
  return h->elements;
177
}
178

    
179
struct peer *peerset_get_peer(const struct peerset *h, const struct nodeID *id)
180
{
181
  int i = peerset_check(h,id);
182
  return (i<0) ? NULL : h->elements[i];
183
}
184

    
185
struct peer *peerset_pop_peer(struct peerset *h, const struct nodeID *id){
186
  int i = peerset_check(h,id);
187
  if (i >= 0) {
188
    struct peer *e = h->elements[i];
189
    memmove(&h->elements[i], &h->elements[i+1], ((h->n_elements--) - (i+1)) * sizeof(struct peer *));
190

    
191
    return e;
192
  }
193
  return NULL;
194
}
195

    
196
int peerset_remove_peer(struct peerset *h, const struct nodeID *id){
197
  int i = peerset_check(h,id);
198
  if (i >= 0) {
199
    struct peer *e = h->elements[i];
200
    nodeid_free(e->id);
201
    chunkID_set_free(e->bmap);
202
    memmove(&h->elements[i], &h->elements[i+1], ((h->n_elements--) - (i+1)) * sizeof(struct peer *));
203
    free(e);
204

    
205
    return i;
206
  }
207
  return -1;
208
}
209

    
210
int peerset_check(const struct peerset *h, const struct nodeID *id)
211
{
212
  struct peer **p;
213

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

    
216
  return p ? p - h->elements : -1;
217
}
218

    
219
void peerset_clear(struct peerset *h, int size)
220
{
221
  int i;
222

    
223
  for (i = 0; i < h->n_elements; i++) {
224
    struct peer *e = h->elements[i];
225
    nodeid_free(e->id);
226
    chunkID_set_free(e->bmap);
227
    free(e);
228
  }
229

    
230
  h->n_elements = 0;
231
  h->size = size;
232
  h->elements = realloc(h->elements, size * sizeof(struct peer *));
233
  if (h->elements == NULL) {
234
    h->size = 0;
235
  }
236
}