BitTorrent Tracker
Tracker init() - La inceput, trackerul apeleaza functia init() unde face MPI_Recv pe datele necesare asteptate de la fiecare client. Acesta adauga in memorie structura TFile care contine informatii despre numele, segmentul si swarm-ul fisierului, fara a memora ce segmente detine fiecare client.
Dupa initializare, trackerul trimite mesaj catre toti clientii prin care ii anunta ca pot incepe descarcarea.
Loop - Trackerul face Irecv si asteapta intr-o bucla while pana la primirea unui mesaj. La primirea unei cereri noi de download de la un client memoreaza clientul in lista de clienti activi. Daca nu exista niciun client activ, asteapta 2 secunde si se opreste, trimitand si mesaje de oprire catre threadurile de upload. Folosirea operatiilor nonblocante Irecv si Isend asigura eficienta maxima, permitand rezolvarea cat mai multor cereri.
Pentru a separa foarte clar tipurile de mesaje, exista mai multe tag-uri explicite.
Intr-o aplicatie reala, trackerul ar fi implementat si posibilitatea noilor clienti de a se conecta, ar fi verificat periodic daca fiecare client mai e conectat si i-ar fi eliminat din swarm-urile existente pe cei deconectati.
Client Dupa citirea datelor de intrare, clientul asteapta mesajul de start de la tracker si porneste thread-urile upload si download. Download: La inceputul threadului de download, clientul cere pentru fiecare fisier dorit de la tracker hash-urile segmentelor si swarm-ul.
Pentru descarcarea fisierelor, se descarca cate 1 segment din fiecare fisier, iar cand se ajunge la 10 se reactualizeaza toate swarm-urile. Desi in contextul temei nu este cea mai eficienta alegere, simuleaza cel mai bine ce se intampla in realitate: se descarca in acelasi timp mai multe fisiere, nu se descarca pe rand. Segmentele se descarca in ordine, si de fiecare data se alege urmatorul swarm pentru acel fisier, de acest lucru ocupandu-se functia get_next_swarm().
Daca un segment nu este gasit la clientul de la care a fost cerut se va incerca de la altul, care sigur il are, pentru ca daca un fisier nu exista pe tracker este scos de la bun inceput din lista fisierelor dorite (adica e marcat ca fiind descarcat), lucru care asigura faptul ca in cazul in care 2 clienti ar cere un fisier care nu exista nu se ajunge la cazul in care sa se intrebe unul pe altul la infinit daca au segmente din el.
Upload: Threadul de upload asteapta intr-o bucla mesaje, care pot fi cereri de download sau mesaj de oprire de la tracker. La primirea unei cereri (care contine numele fisierului, hash-ul segmentului, index-ul segmentului), se cauta in fisierele detinute, apoi in cele in curs de descarcare. Ar fi putut fi adaugat un mutex pe structura TFile pentru a asigura sincronizarea cu threadul de descarcare care ar putea marca intre timp un segment ca fiind descarcat, dar am considerat ca ar fi un overhead inutil, avand in vedere ca din upload se face doar citire.
Cererea de download contine si hash-ul si id-ul segmentului pentru ca m-am gandit ca functia de hash nu e injectiva, si intr-un fisier ar putea exista mai multe segmente cu acelasi hash. Implementarea acestei structuri pentru download_request nu a fost facuta complet, ar fi trebuit creat un tip de date MPI pentru a functiona intre sisteme cu endianess diferit, dar ar fi complicat thread-ul de upload.