Statistics
| Branch: | Tag: | Revision:

sssimulator / ed.c @ 659ba19d

History | View | Annotate | Download (5.68 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 *statusfile;
13

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
139
void ed_simulator_status_print(struct ed_simulator * eds)
140
{
141
        status_print(statusfile, eds->peers, eds->num_peers, eds->chunks, eds->num_chunks, event_scheduler_elapsed_time(eds->sched));
142
}
143

    
144
void ed_simulator_gen_events(struct ed_simulator *eds)
145
{
146
        int i;
147

    
148
        if(eds)
149
        {
150
                ed_simulator_schedule(eds, source_event_new(eds), 0);
151
                for (i = 0; i < eds->num_peers; i++) 
152
                {
153
                        ed_simulator_schedule(eds, peer_offer_event_new(eds, &(eds->peers[i])), 0 );
154
                }
155
        }
156
}
157

    
158
int ed_simulator_events(struct ed_simulator * eds)
159
{
160
        int res = -1;
161
        if (eds)
162
                res = event_scheduler_queue_length(eds->sched);
163
        return res;
164
}
165

    
166
int ed_simulator_num_chunks(struct ed_simulator *eds)
167
{
168
        return eds->num_chunks;
169
}
170

    
171
struct action_event * ed_simulator_pick_event(struct ed_simulator * eds)
172
{
173
        if(eds)
174
                return event_scheduler_pop(eds->sched);
175
        return NULL;
176
}
177

    
178
int ed_simulator_network_activity(struct ed_simulator *eds)
179
{
180
        int i, chunk, t, activity = 0;
181
        struct peer * dst;
182

    
183
        t = ((int) ed_simulator_time(eds));
184
        if (t < eds->num_chunks)
185
                activity = 1;
186

    
187
        i = 0;
188
        while (!activity && i < eds->num_peers)
189
        {
190
                peer_send(&(eds->peers[i]), t, &chunk, &dst);
191
                if (dst)
192
                {
193
                        //fprintf(stderr,"[DEBUG] peer %d has still something to offer\n", dst->id);
194
                        activity = 1;
195
                }
196
                chunk = 0;
197
                while (!activity && chunk < eds->peers[i].buf_size)
198
                {
199
                        if (eds->peers[i].recv_chunks[chunk])
200
                        {
201
                                //fprintf(stderr,"[DEBUG] peer %d has still something to receive %d\n", eds->peers[i].id, chunk);
202
                                activity = 1;
203
                        }
204
                        chunk++;
205
                }
206
                i++;
207
        }
208
        return activity;
209
}
210

    
211
struct chunk *ed_loop(struct peer *p, int np, int num_chunks, int server_period)
212
{
213
        struct ed_simulator * eds;
214
        struct chunk * chunks;
215
        struct action_event * ae;
216

    
217
        chunks = malloc(num_chunks * sizeof(struct chunk));
218
        if (chunks == NULL) {
219
                perror("MAlloc");
220
                return NULL;
221
        }
222
        memset(chunks, 0, num_chunks * sizeof(struct chunk));
223

    
224
        eds = ed_simulator_new(chunks, num_chunks, p, np, server_period);
225
        ed_simulator_gen_events(eds);
226

    
227
        while(ed_simulator_network_activity(eds))
228
        {
229
                //fprintf(stderr,"[DEBUG] another round, time %f\n", ed_simulator_time(eds));
230
                ae = ed_simulator_pick_event(eds);
231
                action_event_trigger(ae);
232
        }
233
        ed_simulator_destroy(&eds);
234

    
235
        return chunks;
236
}