Statistics
| Branch: | Revision:

pstreamer / src / transaction.c @ ffebdf87

History | View | Annotate | Download (7.18 KB)

1
/*
2
 * Copyright (c) 2010-2011 Stefano Traverso
3
 * Copyright (c) 2010-2011 Csaba Kiraly
4
 * Copyright (c) 2017 Luca Baldesi
5
 *
6
 * This file is part of PeerStreamer.
7
 *
8
 * PeerStreamer is free software: you can redistribute it and/or
9
 * modify it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * PeerStreamer is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
16
 * General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with PeerStreamer.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22

    
23
#include <stdint.h>
24
#include <stdio.h>
25
#include <stdbool.h>
26
#include <stdlib.h>
27
#include <sys/time.h>
28

    
29
#include "dbg.h"
30
#include "measures.h"
31
#include "transaction.h"
32

    
33
typedef struct {
34
        uint16_t trans_id;
35
        double offer_sent_time;
36
        double accept_received_time;
37
        struct nodeID *id;
38
        } service_time;
39

    
40
// List to trace peer's service times
41
struct service_times_element {
42
        service_time st;
43
        struct service_times_element *backward;
44
        struct service_times_element *forward;
45
        };
46

    
47

    
48
void _transaction_remove(struct service_times_element ** head, struct service_times_element *stl)
49
{
50
        if (stl->backward == NULL) {
51
                if (stl->forward)
52
                {
53
                        *head = stl->forward;
54
                        (*head)->backward = NULL;
55
                } else
56
                        *head = NULL;
57
        }
58
        else {
59
                if (stl->forward == NULL)
60
                        stl->backward->forward = NULL;
61
                else {
62
                        stl->backward->forward = stl->forward;
63
                        stl->forward->backward = stl->backward;
64
                }
65
        }
66
        nodeid_free(stl->st.id);
67
        free(stl);
68
}        
69

    
70
// Check the service times list to find elements over the timeout
71
void check_neighbor_status_list(struct service_times_element ** stl) {
72
        struct service_times_element *stl_iterator, *stl_aux;
73
        struct timeval current_time;
74
        bool something_got_removed;
75

    
76
        gettimeofday(&current_time, NULL);
77
        something_got_removed = false;
78
        
79
        dprintf("LIST: check trans_id list\n");
80
        
81
        // Check if list is empty
82
        if (*stl == NULL) {
83
                return;
84
                }
85
        
86
        // Start from the beginning of the list
87
        stl_iterator = *stl;
88
        stl_aux = *stl;
89
        // Iterate the list until you get the right element
90
        while (stl_iterator != NULL) {
91
                // If the element has been in the list for a period greater than the timeout, remove it
92
//                if ( (stl_iterator->st.accept_received_time > 0.0 && ( (current_time.tv_sec + current_time.tv_usec*1e-6) - stl_iterator->st.accept_received_time) > TRANS_ID_MAX_LIFETIME) ||  ((current_time.tv_sec + current_time.tv_usec*1e-6) - stl_iterator->st.offer_sent_time > TRANS_ID_MAX_LIFETIME ) ) {
93
                if ( (current_time.tv_sec + current_time.tv_usec*1e-6 - stl_iterator->st.offer_sent_time) > TRANS_ID_MAX_LIFETIME) {
94
                         dprintf("LIST TIMEOUT: trans_id %d, offer_sent_time %f, accept_received_time %f\n", stl_iterator->st.trans_id, (double) ((current_time.tv_sec + current_time.tv_usec*1e-6) - stl_iterator->st.offer_sent_time  ), (double) ((current_time.tv_sec + current_time.tv_usec*1e-6) - stl_iterator->st.accept_received_time));
95
                         //fprintf(stderr, "LIST TIMEOUT: trans_id %d, offer_sent_time %f, accept_received_time %f\n", stl_iterator->st.trans_id, (double) ((current_time.tv_sec + current_time.tv_usec*1e-6) - stl_iterator->st.offer_sent_time  ), (double) ((current_time.tv_sec + current_time.tv_usec*1e-6) - stl_iterator->st.accept_received_time));
96
                _transaction_remove(stl, stl_iterator);
97
                        something_got_removed = true;
98
#ifndef MONL
99
                        timeout_reception_measure(stl_iterator->st.id);
100
#endif
101

    
102
                        stl_aux = stl_iterator->forward;
103
                        // Free the memory
104
                        }
105
                if (something_got_removed) {
106
                        stl_iterator = stl_aux;
107
                        something_got_removed = false;
108
                        }
109
                else
110
                        stl_iterator = stl_iterator->forward;
111
                }
112
        return;
113
}
114

    
115
// register the moment when a transaction is started
116
// return a  new transaction id or 0 in case of failure
117
uint16_t transaction_create(struct service_times_element ** stl, struct nodeID *id)
118
{
119
        struct service_times_element *stl2;
120
        struct timeval current_time;
121

    
122
        if (stl && id)
123
        {
124
                check_neighbor_status_list(stl);
125

    
126
                gettimeofday(&current_time, NULL);
127

    
128

    
129
                // create a new element in the list with its offer_sent_time and set accept_received_time to -1.0
130
                stl2 = (struct service_times_element*) malloc(sizeof(struct service_times_element));
131
                stl2->st.offer_sent_time = current_time.tv_sec + current_time.tv_usec*1e-6;
132
                stl2->st.accept_received_time = -1.0;
133
                stl2->st.id = nodeid_dup(id);
134

    
135
                stl2->backward = NULL;
136

    
137
                if (*stl)
138
                {
139
                        stl2->st.trans_id = (*stl)->st.trans_id + 1 ? (*stl)->st.trans_id + 1 : 1;
140
                        (*stl)->backward = stl2;
141
                        stl2->forward = (*stl);
142
                        *stl = stl2;
143
                } else {
144
                        stl2->st.trans_id = 1;
145
                        stl2->forward = NULL;
146
                        *stl = stl2;
147
                }
148
                dprintf("LIST: adding trans_id %d to the list, offer_sent_time %f -- LIST IS NOT EMPTY\n", stl2->st.trans_id, (current_time.tv_sec + current_time.tv_usec*1e-6));
149

    
150
                return stl2->st.trans_id;
151
        }
152
        return 0;
153
}
154

    
155

    
156
// Add the moment I received a positive select in a list
157
// return true if a valid trans_id is found
158
bool transaction_reg_accept(struct service_times_element * stl, uint16_t trans_id,const struct nodeID *id)
159
{
160
        struct service_times_element *stl_iterator;
161
        struct timeval current_time;
162

    
163
        if (stl && id && trans_id)
164
        {
165
                gettimeofday(&current_time, NULL);
166
                stl_iterator = stl;
167

    
168
                // if an accept was received, look for the trans_id and add current_time to accept_received_time field
169
                dprintf("LIST: changing trans_id %d to the list, accept received %f\n", trans_id, current_time.tv_sec + current_time.tv_usec*1e-6);
170
                // Iterate the list until you get the right element
171
                while (stl_iterator != NULL) {
172
                                if (stl_iterator->st.trans_id == trans_id) {
173
                                        stl_iterator->st.accept_received_time = current_time.tv_sec + current_time.tv_usec*1e-6;
174
        #ifndef MONL
175
                                        offer_accept_rtt_measure(id,stl_iterator->st.accept_received_time - stl_iterator->st.offer_sent_time);
176
                                        reception_measure(id);
177
        #endif
178
                                        return true;
179
                                        }
180
                                stl_iterator = stl_iterator->forward;
181
                }
182
        }
183
        return false;
184
}
185

    
186
// Used to get the time elapsed from the moment I get a positive select to the moment i get the ACK
187
// related to the same chunk
188
// it return -1.0 in case no trans_id is found
189
double transaction_remove(struct service_times_element ** stl, uint16_t trans_id) {
190
        struct service_times_element *stl_iterator;
191
        double to_return;
192

    
193
    dprintf("LIST: deleting trans_id %d\n", trans_id);
194

    
195
        // Start from the beginning of the list
196
        stl_iterator = *stl;
197
        // Iterate the list until you get the right element
198
        while (stl_iterator != NULL) {
199
                if (stl_iterator->st.trans_id == trans_id)
200
                        break;
201
                stl_iterator = stl_iterator->forward;
202
                }
203
        if (stl_iterator == NULL){
204
                // not found
205
        dprintf("LIST: deleting trans_id %d -- STL is already NULL \n", trans_id);
206
                return -2.0;
207
        }
208
        
209
#ifndef MONL
210
        // This function is called when an ACK is received, so:
211
        reception_measure(stl_iterator->st.id);
212
#endif
213

    
214
        to_return = stl_iterator->st.accept_received_time;
215

    
216
        _transaction_remove(stl, stl_iterator);
217

    
218
        return to_return;
219
}
220

    
221
void transaction_destroy(struct service_times_element ** head)
222
{
223
        while(*head)
224
        {
225
                _transaction_remove(head, *head);
226
                // in case of nodeid_dup we should free that as well
227
        }
228

    
229
}