receptionTable.c 3.43 KB
Newer Older
Andreas Schmidt's avatar
Andreas Schmidt committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include "../../defines.h"
#include "../../util/common.h"
#include "../../util/dbg.h"
#include "receptionTable.h"

PrrtReceptionTable *PrrtReceptionTable_create(void) {
    PrrtReceptionTable* t = calloc(1, sizeof(PrrtReceptionTable));
    check_mem(t);
    t->start = 0;
    t->maxNumberInWindow = 0;
    t->windowSize = 1000;
    t->bitmap = Bitmap_create(false, SEQNO_SPACE);

    pthread_mutexattr_t attr;
    check(pthread_mutexattr_init(&attr) == EXIT_SUCCESS, "Mutex attr init failed.");
    check(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == EXIT_SUCCESS, "Setting type failed.");
    check(pthread_mutex_init(&t->lock, &attr) == 0, "Mutex init failed.");

    return t;

    error:
    PERROR("Out of memory.%s", "");
    return NULL;
}

bool PrrtReceptionTable_destroy(PrrtReceptionTable *t) {
    pthread_mutex_destroy(&t->lock);
    Bitmap_destroy(t->bitmap);
    free(t);
    return true;
}

bool PrrtReceptionTable_mark_received(PrrtReceptionTable *t, prrtSequenceNumber_t markedNumber) {
    check(pthread_mutex_lock(&t->lock) == EXIT_SUCCESS, "Lock failed.");
    prrtSequenceNumber_t markedNumber_relative = (prrtSequenceNumber_t) (markedNumber - t->start);
    prrtSequenceNumber_t maxNumberInWindow_relative = (prrtSequenceNumber_t) (t->maxNumberInWindow - t->start);

    if (markedNumber_relative < t->windowSize) {
        Bitmap_set_1(t->bitmap, markedNumber);
        if(markedNumber_relative > maxNumberInWindow_relative) {
            t->maxNumberInWindow = markedNumber;
        }
    }

    if(markedNumber_relative > (t->windowSize/2)) {
        prrtSequenceNumber_t new_start = (prrtSequenceNumber_t) (markedNumber - (t->windowSize / 2));
        Bitmap_set_range_0(t->bitmap, t->start, (prrtSequenceNumber_t ) (new_start - t->start));
        t->start = new_start;
    }
    check(pthread_mutex_unlock(&t->lock) == EXIT_SUCCESS, "Lock failed.");

    return 0;

    error:
    PERROR("PrrtReceptionTable_mark_received failed%s.", "");
    return false;
}

PrrtLossStatistics PrrtReceptionTable_calculate_statistics(PrrtReceptionTable *t) {
    check(pthread_mutex_lock(&t->lock) == EXIT_SUCCESS, "Lock failed.");
    prrtSequenceNumber_t length = (prrtSequenceNumber_t) ((t->maxNumberInWindow - t->start) + 1);
    bool x0 = Bitmap_get(t->bitmap, t->start) == false;
    PrrtLossStatistics statistics = {
            .erasureCount = (uint16_t) x0,
            .packetCount = length,
            .gapCount = (uint16_t) x0,
            .burstCount = (uint16_t) (1 - ((uint16_t) x0)),
    };
    statistics.gapLength = statistics.gapCount;
    statistics.burstLength = statistics.burstCount;
    bool isInGap = x0;
    uint16_t i = 0;
    for(i = 1; i < length; i++) {
        bool currentPosition = Bitmap_get(t->bitmap, t->start + i) == false;
        statistics.erasureCount += currentPosition;
        if(isInGap && currentPosition) {
            statistics.gapLength++;
        } else if(isInGap && (currentPosition == false)) {
            isInGap = false;
            statistics.burstCount++;
            statistics.burstLength++;
        } else if((isInGap == false) && currentPosition) {
            isInGap = true;
            statistics.gapCount++;
            statistics.gapLength++;
        } else {
            statistics.burstLength++;
        }
    }
    check(pthread_mutex_unlock(&t->lock) == EXIT_SUCCESS, "Lock failed.");
    return statistics;

    error:
    PERROR("PrrtReceptionTable_calculate_statistics failed%s.", "");
    return statistics;

}