Statistics
| Branch: | Revision:

grapes / src / TopologyManager / dumbTopman.c @ 176b8de8

History | View | Annotate | Download (5.14 KB)

1
/*
2
 * dumbTopman.c
3
 *
4
 *  Created on: Oct 21, 2010
5
 *      Author: Marco Biazzini
6
 */
7

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

    
15
#include "net_helper.h"
16
#include "../Cache/topocache.h"
17
#include "grapes_config.h"
18
#include "topman_iface.h"
19

    
20
#define DUMB_DEFAULT_MEM        20
21
#define DUMB_DEFAULT_CSIZE        20
22
#define DUMB_DEFAULT_PERIOD        10
23

    
24
static uint64_t currtime;
25
static int memory;
26
static int cache_size;
27
static int current_size;
28
static int mdata_size;
29
static int do_resize;
30
static int period;
31
static struct peer_cache *local_cache;
32
static uint8_t *my_mdata;
33
static struct nodeID *me;
34

    
35
static uint64_t gettime(void)
36
{
37
        struct timeval tv;
38

    
39
        gettimeofday(&tv, NULL);
40

    
41
        return tv.tv_usec + tv.tv_sec * 1000000ull;
42
}
43

    
44
static int time_to_run(void)
45
{
46
        if (gettime() - currtime > period) {
47
                currtime += period;
48
                return 1;
49
        }
50

    
51
        return 0;
52
}
53

    
54
static int dumbInit(struct nodeID *myID, void *metadata, int metadata_size, ranking_function rfun, const char *config)
55
{
56
        struct tag *cfg_tags;
57
        int res;
58

    
59
        cfg_tags = grapes_config_parse(config);
60
        res = grapes_config_value_int(cfg_tags, "cache_size", &cache_size);
61
        if (!res) {
62
                cache_size = DUMB_DEFAULT_CSIZE;
63
        }
64
        res = grapes_config_value_int(cfg_tags, "memory", &memory);
65
        if (!res) {
66
                memory = DUMB_DEFAULT_MEM;
67
        }
68
        res = grapes_config_value_int(cfg_tags, "period", &period);
69
        if (!res) {
70
                period = DUMB_DEFAULT_PERIOD;
71
        }
72
        period *= 1000000;
73

    
74
        local_cache = cache_init(cache_size, metadata_size, 0);
75
        if (local_cache == NULL) {
76
                return -1;
77
        }
78
        mdata_size = metadata_size;
79
        if (mdata_size) {
80
                my_mdata = malloc(mdata_size);
81
                if (my_mdata == NULL) {
82
                        cache_free(local_cache);
83
                        return -1;
84
                }
85
                memcpy(my_mdata, metadata, mdata_size);
86
        }
87
        me = myID;
88
        currtime = gettime();
89

    
90
        return 0;
91
}
92

    
93
static int dumbGivePeers (int n, struct nodeID **peers, void *metadata)
94
{
95
        int metadata_size;
96
        const uint8_t *mdata;
97
        int i;
98

    
99
        mdata = get_metadata(local_cache, &metadata_size);
100
        for (i=0; nodeid(local_cache, i) && (i < n); i++) {
101
                peers[i] = nodeid(local_cache,i);
102
                if (metadata_size)
103
                        memcpy((uint8_t *)metadata + i * metadata_size, mdata + i * metadata_size, metadata_size);
104
        }
105

    
106
        return i;
107
}
108

    
109
static int dumbGetNeighbourhoodSize(void)
110
{
111
        int i;
112

    
113
        for (i = 0; nodeid(local_cache, i); i++);
114

    
115
        return i;
116
}
117

    
118
static int dumbAddNeighbour(struct nodeID *neighbour, void *metadata, int metadata_size)
119
{
120
        if (cache_add(local_cache, neighbour, metadata, metadata_size) < 0) {
121
                return -1;
122
        }
123

    
124
        current_size++;
125
        return 1;
126
}
127

    
128
static const void *dumbGetMetadata(int *metadata_size)
129
{
130
        return get_metadata(local_cache, metadata_size);
131
}
132

    
133
static int dumbChangeMetadata(void *metadata, int metadata_size)
134
{
135
        if (metadata_size && metadata_size == mdata_size) {
136
                memcpy(my_mdata, (uint8_t *)metadata, mdata_size);
137
                return 1;
138
        }
139
        else return -1;
140
}
141

    
142
static int dumbParseData(const uint8_t *buff, int len, struct nodeID **peers, int size, const void *metadata, int metadata_size)
143
{
144
        struct peer_cache *new_cache;
145
        const uint8_t *m_data;
146
        int r,j, msize, csize, heritage;
147

    
148
        if (!time_to_run()) {
149
                return 1;
150
        }
151
        if (metadata_size != mdata_size) {
152
                fprintf(stderr, "DumbTopman : Metadata size mismatch with peer sampler!\n");
153
                return 1;
154
        }
155
        if (!size) {
156
                fprintf(stderr, "DumbTopman : No peer available from peer sampler!\n");
157
        }
158

    
159
        m_data = (const uint8_t *)get_metadata(local_cache, &msize);
160
        new_cache = cache_init(cache_size, msize, 0);
161
        if (!new_cache) {
162
                fprintf(stderr, "DumbTopman : Memory error while creating new cache!\n");
163
                return 1;
164
        }
165

    
166
        cache_update(local_cache);
167
        heritage = (cache_size * memory) / 100;
168
        if (heritage > current_size) {
169
                heritage = current_size;
170
        }
171
        for (csize = 0; csize < heritage; ) {
172
                if (heritage == current_size) {
173
                        r = csize;
174
                } else {
175
                        r = ((double)rand() / (double)RAND_MAX) * current_size;
176
                        if (r == current_size) r--;
177
                }
178
                r = cache_add(new_cache, nodeid(local_cache, r), m_data + r * msize, msize);
179
                if (csize < r) {
180
                        csize = r;
181
                }
182
        }
183
        for (j = 0; j < size && csize < cache_size; j++) {
184
                r = cache_add(new_cache, peers[j], (const uint8_t *)metadata + j * metadata_size,
185
                        metadata_size);
186
                if (csize < r) {
187
                        csize = r;
188
                }
189
        }
190
        current_size = csize;
191
        cache_free(local_cache);
192
        local_cache = new_cache;
193
        do_resize = 0;
194

    
195
        fprintf(stderr, "DumbTopman : Parse Data.\n");
196
        return 0;
197
}
198

    
199
// limit : at most it doubles the current cache size...
200
static int dumbGrowNeighbourhood(int n)
201
{
202
        if (n <= 0 || do_resize)
203
                return -1;
204
        n = n > cache_size ? cache_size : n;
205
        cache_size += n;
206
        do_resize = 1;
207
        return cache_size;
208
}
209

    
210
static int dumbShrinkNeighbourhood(int n)
211
{
212
        if (n <= 0 || n >= cache_size || do_resize)
213
                return -1;
214
        cache_size -= n;
215
        do_resize = 1;
216
        return cache_size;
217
}
218

    
219
static int dumbRemoveNeighbour(struct nodeID *neighbour)
220
{
221
        current_size = cache_del(local_cache, neighbour);
222
        return current_size;
223
}
224

    
225

    
226
struct topman_iface dumb = {
227
        .init = dumbInit,
228
        .changeMetadata = dumbChangeMetadata,
229
        .addNeighbour = dumbAddNeighbour,
230
        .parseData = dumbParseData,
231
        .givePeers = dumbGivePeers,
232
        .getMetadata = dumbGetMetadata,
233
        .growNeighbourhood = dumbGrowNeighbourhood,
234
        .shrinkNeighbourhood = dumbShrinkNeighbourhood,
235
        .removeNeighbour = dumbRemoveNeighbour,
236
        .getNeighbourhoodSize = dumbGetNeighbourhoodSize,
237
};