Statistics
| Branch: | Tag: | Revision:

sssimulator / ed.c @ 4123e0f7

History | View | Annotate | Download (6.64 KB)

1
/*
2
 * this is sssim: the simple & stupid simulator
3
 *
4
 *  copyright (c) 2015 luca baldesi
5
 *
6
 *  this is free software; see gpl-3.0.txt
7
 */
8

    
9
#include "ed.h"
10
#include <stdint.h>
11

    
12
FILE *resfile;
13
FILE *delayfile;
14
FILE *statusfile;
15
extern float convergence_precision;
16
extern uint32_t analysis_window;
17
extern int per_link_events;
18

    
19
struct ed_simulator {
20
        struct chunk * chunks;
21
        struct peer * peers;
22
        struct event_scheduler * sched;
23
        int num_chunks;
24
        int num_peers;
25
        int ts;
26
};
27

    
28
struct ed_simulator * ed_simulator_new(struct chunk * c, int num_chunks, struct peer * peers, int num_peers, int server_period)
29
{
30
        struct ed_simulator * eds;
31

    
32
        eds = (struct ed_simulator *) malloc (sizeof(struct ed_simulator));
33
        eds->sched = event_scheduler_new(0);
34
        eds->chunks = c;
35
        eds->ts = server_period;
36
        eds->peers = peers;
37
        eds->num_chunks = num_chunks;
38
        eds->num_peers = num_peers;
39
        return eds;
40
}
41

    
42
double ed_simulator_time(const struct ed_simulator *eds)
43
{
44
        return event_scheduler_elapsed_time(eds->sched);
45
}
46

    
47
int ed_simulator_server_period(const struct ed_simulator *eds)
48
{
49
        return eds->ts;
50
}
51

    
52
void ed_simulator_destroy(struct ed_simulator ** eds)
53
{
54
        struct action_event * ae;
55

    
56
        if(eds && *eds)
57
        {
58
                while(event_scheduler_queue_length(((*eds)->sched)))
59
                {
60
                        ae = event_scheduler_pop(((*eds)->sched));
61
                        action_event_destroy(&ae);
62
                }
63
                event_scheduler_destroy(&((*eds)->sched));
64
                free(*eds);
65
                *eds = NULL;
66
        }
67
}
68

    
69
void ed_simulator_inc_chunk_counter(struct ed_simulator * eds, int k)
70
{
71
        if (eds && eds->chunks && eds->num_chunks > k)
72
                eds->chunks[k].received += 1;        
73
}
74

    
75
void ed_simulator_update_chunk_delay(struct ed_simulator * eds, int k)
76
{
77
        int gen_time;
78
        float delay;
79

    
80
        gen_time = k;
81
        if (eds && eds->chunks && eds->num_chunks > k)
82
        {
83
                delay = event_scheduler_elapsed_time(eds->sched) - gen_time;
84
//                fprintf(stderr,"[DEBUG] delay: %f\n", delay);
85
                eds->chunks[k].avg_delay += delay;
86
                eds->chunks[k].max_delay = max(eds->chunks[k].max_delay, delay);
87
        }
88
}
89

    
90
void ed_simulator_schedule(struct ed_simulator * eds, struct action_event * ae, double interval)
91
{
92
        if(eds && ae)
93
        {
94
                event_scheduler_insert(eds->sched, ae, interval, LOW_EVENT_PRIORITY);
95
        }
96
}
97

    
98
void ed_simulator_send_chunk(struct ed_simulator * eds, int chunk, struct peer * dst, float dl)
99
{
100
        int idx;
101

    
102
//        fprintf(stderr,"[DEBUG] sending %d\n", chunk);
103
        if(eds && dst && chunk < eds->num_chunks && dl >= 0)
104
        {
105
                idx = win_idx(dst, chunk);
106
                if(dst->recv_chunks[idx])
107
                        fprintf(stderr,"[ERROR] sending a chunk to a peer which is already receiving it\n");
108
                if(dst->chunks[idx])
109
                {
110
                        dst->recv_chunks[idx] = dst->chunks[idx]; // we reuse the same struct avoiding mallocs
111
                        dst->chunks[idx] = NULL;
112
                } else
113
                        dst->recv_chunks[idx] = (struct chunk_instance *) malloc (sizeof(struct chunk_instance));
114

    
115
                dst->recv_chunks[idx]->chunk = chunk;
116
                dst->recv_chunks[idx]->dl = dl;
117
                dst->latest_not_needed = max(chunk, dst->latest_not_needed);
118
                ed_simulator_inc_chunk_counter(eds, chunk);
119
                event_scheduler_insert(eds->sched, peer_reception_event_new(eds, dst, chunk), RECEPTION_DELAY, HIGH_EVENT_PRIORITY);
120
        }
121
}
122

    
123
void ed_simulator_receive_chunk(struct ed_simulator *eds, struct peer *p, int chunk)
124
{
125
        int idx;
126

    
127
        //fprintf(stderr,"[DEBUG] receiving %d\n", chunk);
128
        idx = win_idx(p, chunk);
129
        if(p->recv_chunks[idx])
130
        {
131
                p->chunks[idx] = p->recv_chunks[idx];
132
                p->recv_chunks[idx] = NULL;
133
                p->chunks[idx]->completed = event_scheduler_elapsed_time(eds->sched);
134
//                fprintf(stderr,"[DEBUG] peer %d receives chunk %d ", p->id, chunk);
135
                ed_simulator_update_chunk_delay(eds, chunk);
136
                if (delayfile) {
137
                    fprintf(delayfile, "%f,%d,%d,%f\n", ed_simulator_time(eds), p->id, p->chunks[idx]->chunk, ed_simulator_time(eds) - p->chunks[idx]->chunk);
138
                    fflush(delayfile);
139
                }
140
                if (eds->chunks[chunk].received == eds->num_peers && resfile) 
141
                {
142
                    fprintf(resfile, "Chunk %d received at %f in %f\n", p->chunks[idx]->chunk, ed_simulator_time(eds), ed_simulator_time(eds) - p->chunks[idx]->chunk);
143
                    fflush(resfile);
144
                }
145
        }
146
}
147

    
148
void ed_simulator_status_print(struct ed_simulator * eds)
149
{
150
        status_print(statusfile, eds->peers, eds->num_peers, eds->chunks, eds->num_chunks, event_scheduler_elapsed_time(eds->sched));
151
}
152

    
153
void ed_simulator_gen_events(struct ed_simulator *eds)
154
{
155
        int i, j;
156

    
157
        if(eds)
158
        {
159
                ed_simulator_schedule(eds, source_event_new(eds), 0);
160
                for (i = 0; i < eds->num_peers; i++) 
161
                        if (per_link_events)
162
                                for (j = 0; j < eds->peers[i].neigh_size; j++) 
163
                                        ed_simulator_schedule(eds, link_offer_event_new(eds, &(eds->peers[i]), j), 0 );
164
                        else
165
                                ed_simulator_schedule(eds, peer_offer_event_new(eds, &(eds->peers[i])), 0 );
166
        }
167
}
168

    
169
int ed_simulator_events(struct ed_simulator * eds)
170
{
171
        int res = -1;
172
        if (eds)
173
                res = event_scheduler_queue_length(eds->sched);
174
        return res;
175
}
176

    
177
int ed_simulator_num_chunks(struct ed_simulator *eds)
178
{
179
        return eds->num_chunks;
180
}
181

    
182
struct action_event * ed_simulator_pick_event(struct ed_simulator * eds)
183
{
184
        if(eds)
185
                return event_scheduler_pop(eds->sched);
186
        return NULL;
187
}
188

    
189
int ed_simulator_network_activity(struct ed_simulator *eds)
190
{
191
        int i, chunk, t, activity = 0;
192
        struct peer * dst;
193
        FILE *swap = trace;
194

    
195
        trace = NULL; //disable tracing
196

    
197
        t = ((int) ed_simulator_time(eds));
198
        if (t < eds->num_chunks)
199
                activity = 1;
200

    
201
        i = 0;
202
        while (!activity && i < eds->num_peers)
203
        {
204
                peer_send(&(eds->peers[i]), t, &chunk, &dst);
205
                if (dst)
206
                {
207
                        //fprintf(stderr,"[DEBUG] peer %d has still something to offer\n", dst->id);
208
                        activity = 1;
209
                }
210
                chunk = 0;
211
                while (!activity && chunk < eds->peers[i].buf_size)
212
                {
213
                        if (eds->peers[i].recv_chunks[chunk])
214
                        {
215
                                //fprintf(stderr,"[DEBUG] peer %d has still something to receive %d\n", eds->peers[i].id, chunk);
216
                                activity = 1;
217
                        }
218
                        chunk++;
219
                }
220
                i++;
221
        }
222
        trace = swap; // re-enable tracing
223
        return activity;
224
}
225

    
226
struct chunk *ed_loop(struct peer *p, int np, int num_chunks, int server_period)
227
{
228
        struct ed_simulator * eds;
229
        struct chunk * chunks;
230
        struct action_event * ae;
231
        struct stats * stat = NULL;
232

    
233
        chunks = malloc(num_chunks * sizeof(struct chunk));
234
        if (chunks == NULL) {
235
                perror("MAlloc");
236
                return NULL;
237
        }
238
        memset(chunks, 0, num_chunks * sizeof(struct chunk));
239

    
240
        eds = ed_simulator_new(chunks, num_chunks, p, np, server_period);
241
        ed_simulator_gen_events(eds);
242

    
243
        while(ed_simulator_network_activity(eds) &&
244
                        !(convergence_precision && 
245
                         chunk_stats_converge(&stat, chunks, num_chunks, p, np, ed_simulator_time(eds), analysis_window)))
246
        {
247
                //fprintf(stderr,"[DEBUG] another round, time %f\n", ed_simulator_time(eds));
248
                ae = ed_simulator_pick_event(eds);
249
                action_event_trigger(ae);
250
                //chunk_stats_print(stat, PLAIN_STATS);
251
        }
252
        chunk_stats_converge(&stat, chunks, num_chunks, p, np, ed_simulator_time(eds), analysis_window);
253
        chunk_stats_print(stat, CSV_STATS);
254
        if(stat)
255
                free(stat);
256
        ed_simulator_destroy(&eds);
257

    
258
        return chunks;
259
}