Statistics
| Branch: | Tag: | Revision:

sssimulator / ed.c @ 80f4c362

History | View | Annotate | Download (6.01 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

    
11
FILE *resfile;
12
FILE *delayfile;
13
FILE *statusfile;
14

    
15
struct ed_simulator {
16
        struct chunk * chunks;
17
        struct peer * peers;
18
        struct event_scheduler * sched;
19
        int num_chunks;
20
        int num_peers;
21
        int ts;
22
};
23

    
24
struct ed_simulator * ed_simulator_new(struct chunk * c, int num_chunks, struct peer * peers, int num_peers, int server_period)
25
{
26
        struct ed_simulator * eds;
27

    
28
        eds = (struct ed_simulator *) malloc (sizeof(struct ed_simulator));
29
        eds->sched = event_scheduler_new(0);
30
        eds->chunks = c;
31
        eds->ts = server_period;
32
        eds->peers = peers;
33
        eds->num_chunks = num_chunks;
34
        eds->num_peers = num_peers;
35
        return eds;
36
}
37

    
38
double ed_simulator_time(const struct ed_simulator *eds)
39
{
40
        return event_scheduler_elapsed_time(eds->sched);
41
}
42

    
43
int ed_simulator_server_period(const struct ed_simulator *eds)
44
{
45
        return eds->ts;
46
}
47

    
48
void ed_simulator_destroy(struct ed_simulator ** eds)
49
{
50
        struct action_event * ae;
51

    
52
        if(eds && *eds)
53
        {
54
                while(event_scheduler_queue_length(((*eds)->sched)))
55
                {
56
                        ae = event_scheduler_pop(((*eds)->sched));
57
                        action_event_destroy(&ae);
58
                }
59
                event_scheduler_destroy(&((*eds)->sched));
60
                free(*eds);
61
                *eds = NULL;
62
        }
63
}
64

    
65
void ed_simulator_inc_chunk_counter(struct ed_simulator * eds, int k)
66
{
67
        if (eds && eds->chunks && eds->num_chunks > k)
68
                eds->chunks[k].received += 1;        
69
}
70

    
71
void ed_simulator_update_chunk_delay(struct ed_simulator * eds, int k)
72
{
73
        int gen_time;
74
        float delay;
75

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

    
86
void ed_simulator_schedule(struct ed_simulator * eds, struct action_event * ae, double interval)
87
{
88
        if(eds && ae)
89
        {
90
                event_scheduler_insert(eds->sched, ae, interval, LOW_EVENT_PRIORITY);
91
        }
92
}
93

    
94
void ed_simulator_send_chunk(struct ed_simulator * eds, int chunk, struct peer * dst, float dl)
95
{
96
        int idx;
97

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

    
111
                dst->recv_chunks[idx]->chunk = chunk;
112
                dst->recv_chunks[idx]->dl = dl;
113
                dst->latest_not_needed = max(chunk, dst->latest_not_needed);
114
                ed_simulator_inc_chunk_counter(eds, chunk);
115
                event_scheduler_insert(eds->sched, peer_reception_event_new(eds, dst, chunk), RECEPTION_DELAY, HIGH_EVENT_PRIORITY);
116
        }
117
}
118

    
119
void ed_simulator_receive_chunk(struct ed_simulator *eds, struct peer *p, int chunk)
120
{
121
        int idx;
122

    
123
        //fprintf(stderr,"[DEBUG] receiving %d\n", chunk);
124
        idx = win_idx(p, chunk);
125
        if(p->recv_chunks[idx])
126
        {
127
                p->chunks[idx] = p->recv_chunks[idx];
128
                p->recv_chunks[idx] = NULL;
129
                p->chunks[idx]->completed = event_scheduler_elapsed_time(eds->sched);
130
//                fprintf(stderr,"[DEBUG] peer %d receives chunk %d ", p->id, chunk);
131
                ed_simulator_update_chunk_delay(eds, chunk);
132
                if (delayfile) {
133
                    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);
134
                    fflush(delayfile);
135
                }
136
                if (eds->chunks[chunk].received == eds->num_peers && resfile) 
137
                {
138
                    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);
139
                    fflush(resfile);
140
                }
141
        }
142
}
143

    
144
void ed_simulator_status_print(struct ed_simulator * eds)
145
{
146
        status_print(statusfile, eds->peers, eds->num_peers, eds->chunks, eds->num_chunks, event_scheduler_elapsed_time(eds->sched));
147
}
148

    
149
void ed_simulator_gen_events(struct ed_simulator *eds)
150
{
151
        int i;
152

    
153
        if(eds)
154
        {
155
                ed_simulator_schedule(eds, source_event_new(eds), 0);
156
                for (i = 0; i < eds->num_peers; i++) 
157
                {
158
                        ed_simulator_schedule(eds, peer_offer_event_new(eds, &(eds->peers[i])), 0 );
159
                }
160
        }
161
}
162

    
163
int ed_simulator_events(struct ed_simulator * eds)
164
{
165
        int res = -1;
166
        if (eds)
167
                res = event_scheduler_queue_length(eds->sched);
168
        return res;
169
}
170

    
171
int ed_simulator_num_chunks(struct ed_simulator *eds)
172
{
173
        return eds->num_chunks;
174
}
175

    
176
struct action_event * ed_simulator_pick_event(struct ed_simulator * eds)
177
{
178
        if(eds)
179
                return event_scheduler_pop(eds->sched);
180
        return NULL;
181
}
182

    
183
int ed_simulator_network_activity(struct ed_simulator *eds)
184
{
185
        int i, chunk, t, activity = 0;
186
        struct peer * dst;
187
        FILE *swap = trace;
188

    
189
        trace = NULL; //disable tracing
190

    
191
        t = ((int) ed_simulator_time(eds));
192
        if (t < eds->num_chunks)
193
                activity = 1;
194

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

    
220
struct chunk *ed_loop(struct peer *p, int np, int num_chunks, int server_period)
221
{
222
        struct ed_simulator * eds;
223
        struct chunk * chunks;
224
        struct action_event * ae;
225

    
226
        chunks = malloc(num_chunks * sizeof(struct chunk));
227
        if (chunks == NULL) {
228
                perror("MAlloc");
229
                return NULL;
230
        }
231
        memset(chunks, 0, num_chunks * sizeof(struct chunk));
232

    
233
        eds = ed_simulator_new(chunks, num_chunks, p, np, server_period);
234
        ed_simulator_gen_events(eds);
235

    
236
        while(ed_simulator_network_activity(eds))
237
        {
238
                //fprintf(stderr,"[DEBUG] another round, time %f\n", ed_simulator_time(eds));
239
                ae = ed_simulator_pick_event(eds);
240
                action_event_trigger(ae);
241
        }
242
        ed_simulator_destroy(&eds);
243

    
244
        return chunks;
245
}