Skip to content

Commit

Permalink
No memory leaks in test + fixed typos
Browse files Browse the repository at this point in the history
  • Loading branch information
Sébastien d'Herbais de Thun committed Oct 31, 2019
1 parent 705d7be commit f791678
Show file tree
Hide file tree
Showing 13 changed files with 75 additions and 30 deletions.
5 changes: 3 additions & 2 deletions headers/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ typedef struct config_receiver {

/** Output file name format length */
size_t format_len;

/** Is the format on the heap or the stack? */
bool deallocate_format;

/** Output file name format */
char *format;
Expand All @@ -65,8 +68,6 @@ typedef struct config_receiver {

/** The input port */
uint16_t port;


} config_rcv_t;

/**
Expand Down
2 changes: 1 addition & 1 deletion report/sections/annexes.tex
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ \subsection{Tests d'interopérabilité}
champ \textit{window} était mauvaise. Ils avaient compris que ce champ indiquait la taille de notre \textit{window} et non l'espace restant dans celle-ci.

Notre deuxième test s'est passé de manière beaucoup plus fluide puisque le groupe 85 avait, comme nous, déjà corrigé les bugs d'interopérabilité.
Nous avons donc pus transmettre nos fichiers sans aucun problèmes.
Nous avons donc transmit nos fichiers sans aucun problèmes.


\end{document}
17 changes: 9 additions & 8 deletions report/sections/architecture.tex
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ \subsection{\textit{Streams} - file de communication}
au \textit{receiver} de ne jamais attendre pour insérer dans le stream. En revanche l'opération \textit{dequeue} est protégée par un \textit{mutex} et
emploie une variable conditionnelle\footnote{ Permet de déverouiller un \textit{mutex} en attendant d'être notifié. Un autre \textit{thread} peut ensuite notifier
la condition et le \textit{mutex} sera automatiquement reverouillé. Il est intéressant de noter que la documentation mentionne qu'il est autorisé
de notifier une variable conditionelle sans posséder le \textit{mutex} ce qui permet de maintenir le \textit{dequeue} sans verrou. } pour attendre la dispobilité de nouveaux éléments.
de notifier une variable conditionelle sans posséder le \textit{mutex} ce qui permet de maintenir le \textit{dequeue} sans verrou. } pour attendre la disponibilité de nouveaux éléments.

\subsection{\textit{Syscalls} avancés - \textit{recvmmsg} \& \textit{sendmmsg}}
\label{sec:syscalls}
Expand Down Expand Up @@ -130,12 +130,12 @@ \subsection{Multiple \textit{Pipelines} \& \textit{Affinities} - optimisation de

Ce premier fichier de configuration est accompagné d'un deuxième fichier de configuration, lui aussi tout à fait optionnel, qui permet de définir les affinités
de chaque \textit{receiver} et de chaque \textit{handler}. Cela revient à manuellement définir le coeur physique du \textit{CPU} sur lequel le \textit{thread}
doit tourner. Cela permet de faire deux choses très importantes pour maximiser les performances : la première étant de stabiliser la vitesse de transfer
doit tourner. Cela permet de faire deux choses très importantes pour maximiser les performances : la première étant de stabiliser la vitesse de transfert
en évitant que le \textit{scheduler} déplace les \textit{threads} pendant l'exécution, la deuxième étant de bénéficier de la \textit{core locality}.

Le nombre de \textit{receiver} et \textit{handler threads} sont respectivement contrôllés par deux paramètres additionels : \textit{N} et \textit{n}. Ces deux
valeurs doivent évidemment correspondre avec les fichiers de configuration. Les valeurs de base de ces options sont 1 et 2 afin de maintenir un rapport
(trouvé expérimentalement) de 0.5 qui semble être idéal dans la plupart des cas.
(trouvé expérimentalement) de 0.5 qui semble donner de bons résultats dans la majorité des cas.


\subsubsection{\textit{Core locality}}
Expand All @@ -144,22 +144,23 @@ \subsubsection{\textit{Core locality}}
Cela veut dire que la communication entre ces coeurs se fera plus rapidement qu'entre des coeurs de groupes séparés. Ce phénomène est normalement gênant, mais
en utilisant l'affinité et la configuration des \textit{streams}, il est possible d'agencer les \textit{threads} d'une façon optimale sans procéder à des essais
mais juste en comprenant l'architecture du processeurs. A nouveau, c'est une optimisation tout à fait optionelle qui est simplement utilisée afin de maximiser
les performances dans les tests.
les performances dans les tests. L'impact de la localité sera encore discuté dans les annexes en parlant de l'environement de test.

\subsection{Mode séquentiel}
\label{sec:sequential}

Le mode séquentiel est activé en utilisant l'option \textit{s} qui a été rajoutée au \textit{receiver}. Il permet simplement de faire
tourner notre implémentation sans le moindre \textit{thread} (en dehors de la \textit{main}). Ce mode a toujours de bonnes performances et ignore totalement
les fichiers de configurations et paramètres additionels. Il a été ajouté afin de respecter totalement la spécification et le conseil de ne pas utiliser de
threads. Cependant, ce n'est pas le mode de base.
threads. Cependant, ce n'est pas le mode de base et donne de moins bons résultats car tous les \textit{mutex} et les opérations sur les fichiers font partis
de la boucle d'exécution ce qui ralenti très fort l'exécution. Le \textit{bottleneck} dans ce mode rest cependant le calcul des \textit{CRC32}.

\subsection{Stratégie de tests}
\label{sec:tests}

Nous avons testé chaque librairie séparément pour nous assurer qu'elles effectuaient ce à quoi nous nous attendions et ce en l'absence de tout \textit{memory leak}.
Grâce à çelà, programmer les fonctions plus complexes telles que \textit{handler} a été facilité puisque nous savions que nos librairies ne causaient pas de
problème d'elles mêmes.
Chaque composant a été séparément testé pour s'assurer qu'ils effectuaient ce pour quoi ils avaient été conçus sans le moindre \textit{memory leak}.
Grâce à çelà, la programmation des fonctions plus complexes telles que \textit{handler} a été facilités par l'usage des différents composants et dans
l'assurance que les problèmes ne viendraient pas desdits composants.


\end{document}
4 changes: 4 additions & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ int parse_receiver(int argc, char *argv[], config_rcv_t *config) {

memcpy(o, old, len - 1);
o[len-1] = '\0';

config->deallocate_format = true;
} else {
config->deallocate_format = false;
}

/* format regex - to ensure one and only one %d in format */
Expand Down
1 change: 1 addition & 0 deletions src/hash_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ inline uint16_t ht_hash(ht_t *table, uint16_t port) {
*/
int allocate_ht(ht_t *table) {
table->size = INITIAL_SIZE;
table->length = 0;

table->items = calloc(INITIAL_SIZE, sizeof(item_t));
if (table->items == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion src/stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ int initialize_node(s_node_t *node, void *(*allocator)()) {
* Refer to headers/stream.h
*/
void deallocate_node(s_node_t *node) {
TRACE("Deallocating a stream node\n");
//TRACE("Deallocating a stream node\n");
if (node == NULL) {
return;
}
Expand Down
32 changes: 32 additions & 0 deletions tests/cli_test.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
#include "./headers/cli_test.h"

void free_config_contents(config_rcv_t *config) {
if (config->format && config->deallocate_format) {
free(config->format);
}

if (config->addr_info != NULL) {
freeaddrinfo(config->addr_info);
}

if (config->receive_affinities != NULL) {
free(config->receive_affinities);
}

if (config->handle_affinities != NULL) {
free(config->handle_affinities);
}

if (config->handle_streams != NULL) {
free(config->handle_streams);
}

if (config->receive_streams != NULL) {
free(config->receive_streams);
}
}

void test_cli_noopt() {
config_rcv_t config;
memset(&config, 0, sizeof(config_rcv_t));

char *p_1 = "trtp_receiver";
char *p0 = "::1";
Expand All @@ -13,10 +40,13 @@ void test_cli_noopt() {
CU_ASSERT(strcmp(config.format, "%d") == 0);
CU_ASSERT(config.max_connections == 100);
CU_ASSERT(config.port == 1234);

free_config_contents(&config);
}

void test_cli_all_opt() {
config_rcv_t config;
memset(&config, 0, sizeof(config_rcv_t));

char *p_1 = "trtp_receiver";
char *p0 = "-m";
Expand All @@ -31,6 +61,8 @@ void test_cli_all_opt() {
CU_ASSERT(strcmp(config.format, "my_file_with_space_%d") == 0);
CU_ASSERT(config.max_connections == 128);
CU_ASSERT(config.port == 1234);

free_config_contents(&config);
}

int add_cli_tests() {
Expand Down
8 changes: 5 additions & 3 deletions tests/handler_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
#include "../headers/handler.h"

void test_global() {
int whatever_that_is = 28;
int addrlen = sizeof(struct sockaddr_in6);

struct sockaddr_in6 address;
memset(&address, 0, addrlen);
address.sin6_addr.__in6_u.__u6_addr32[0] = 0;
address.sin6_addr.__in6_u.__u6_addr32[1] = 0;
address.sin6_addr.__in6_u.__u6_addr32[2] = 0;
Expand All @@ -17,7 +18,7 @@ void test_global() {

int send_sock = socket(AF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, 0);
CU_ASSERT(send_sock > 0);
CU_ASSERT( bind(send_sock, &address, whatever_that_is) == 0);
CU_ASSERT( bind(send_sock, &address, addrlen) == 0);

uint8_t buf[528];
packet_t received;
Expand All @@ -44,7 +45,7 @@ void test_global() {
cfg->sockfd = sockfd;

client_t client;
CU_ASSERT(initialize_client(&client, 0, "./bin/%d", &address, &whatever_that_is) == 0);
CU_ASSERT(initialize_client(&client, 0, "./bin/%d", &address, &addrlen) == 0);

packet_t **decoded = alloca(sizeof(packet_t *));
CU_ASSERT(decoded != NULL);
Expand All @@ -69,6 +70,7 @@ void test_global() {

memset(&msg[i], 0, sizeof(struct mmsghdr));
msg[i].msg_hdr.msg_iov = &hd_iovecs[i];
msg[i].msg_hdr.msg_name = NULL;
msg[i].msg_hdr.msg_iovlen = 1;
msg[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_in6);
}
Expand Down
2 changes: 2 additions & 0 deletions tests/ht_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

void test_ht_put_and_get() {
ht_t table;
memset(&table, 0, sizeof(ht_t));
int res = allocate_ht(&table);
CU_ASSERT(res == 0);
if (res != 0) {
Expand All @@ -16,6 +17,7 @@ void test_ht_put_and_get() {
uint16_t i;
for (i = 0; i < N; i++) {
client_t *client = malloc(sizeof(client_t));
memset(client, 0, sizeof(client_t));
client->lock = NULL;
client->out_file = NULL;
client->active = false;
Expand Down
22 changes: 11 additions & 11 deletions tests/packet_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ void test_ack_encoding() {
uint8_t *packed = malloc(sizeof(uint8_t) * 1024);
CU_ASSERT(pack(packed, &packet, false) == 0);

int i;
for(i = 0; i < sizeof(ack_packet); i++) {
CU_ASSERT(ack_packet[i] == (*packed++));
}
CU_ASSERT(memcmp(ack_packet, packed, sizeof(ack_packet)) == 0);

free(packed);
}

void test_data_decoding() {
Expand Down Expand Up @@ -129,7 +128,7 @@ void test_data_encoding() {
uint32_t crc2 = crc32_16bytes_prefetch((void*) str, len, 0, len);
uint32_t crc2_n = htonl(crc2);

uint8_t dat_packet[29] = {
uint8_t dat_packet[] = {
// Type + TR + Window
0b01001010,

Expand Down Expand Up @@ -168,6 +167,7 @@ void test_data_encoding() {
memcpy(dat_packet + 11 + len, &crc2_n, sizeof(uint32_t));

packet_t packet;
init_packet(&packet);
packet.type = DATA;
packet.truncated = false;
packet.window = 0b01010;
Expand All @@ -178,13 +178,13 @@ void test_data_encoding() {
memcpy(&packet.payload, (uint8_t *) str, strlen(str));
packet.crc2 = crc2;

uint8_t *packed = malloc(sizeof(uint8_t) * 1024);
CU_ASSERT(pack(packed, &packet, false) == 0);
uint8_t *packed = malloc(sizeof(uint8_t) * MAX_PACKET_SIZE);
memset(packed, 0, sizeof(uint8_t) * MAX_PACKET_SIZE);
CU_ASSERT(pack(packed, &packet, true) == 0);

int i;
for(i = 0; i < sizeof(dat_packet); i++) {
CU_ASSERT(dat_packet[i] == (*packed++));
}
CU_ASSERT(memcmp(dat_packet, packed, sizeof(dat_packet)) == 0);

free(packed);
}

int add_packet_tests() {
Expand Down
6 changes: 3 additions & 3 deletions tests/receiver_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ void test_receiver() {
struct iovec iovecs[31]; //done

struct sockaddr_in6 address;
memset(&address, 0, sizeof(struct sockaddr_in6));
address.sin6_addr.__in6_u.__u6_addr32[0] = 0;
address.sin6_addr.__in6_u.__u6_addr32[1] = 0;
address.sin6_addr.__in6_u.__u6_addr32[2] = 0;
Expand All @@ -23,6 +24,7 @@ void test_receiver() {

int i;
for(i = 0; i < 31; i++) {
memset(&buffers[i], 0, MAX_PACKET_SIZE);
memset(&iovecs[i], 0, sizeof(struct iovec));
memset(&msgs[i], 0, sizeof(struct mmsghdr));

Expand All @@ -46,10 +48,8 @@ void test_receiver() {
ht_t clients;
CU_ASSERT(allocate_ht(&clients) == 0);




rx_cfg_t cfg;
memset(&cfg, 0, sizeof(rx_cfg_t));
cfg.id = 0;
cfg.thread = NULL;
int idx = 0;
Expand Down
2 changes: 1 addition & 1 deletion tests/stream_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void test_many() {
CU_ASSERT(node != NULL);
if (node != NULL) {
CU_ASSERT(*((int *) node->content) == i);
free(node);
deallocate_node(node);
}

//CU_ASSERT(stream.length == 1023 - i);
Expand Down
2 changes: 2 additions & 0 deletions tests/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ int main() {
add_receiver_tests();

CU_basic_run_tests();

CU_cleanup_registry();

return CU_get_error();
}

0 comments on commit f791678

Please sign in to comment.