#include <mpi.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define TRACKER_RANK 0
#define MAX_FILES 10
#define MAX_FILENAME 15
#define HASH_SIZE 32
#define MAX_CHUNKS 100

void *download_thread_func(void *arg)
{
    int rank = *(int*) arg;

    return NULL;
}

void *upload_thread_func(void *arg)
{
    int rank = *(int*) arg;

    return NULL;
}

void tracker(int numtasks, int rank) {

}

void peer(int numtasks, int rank) {
    pthread_t download_thread;
    pthread_t upload_thread;
    void *status;
    int r;

    r = pthread_create(&download_thread, NULL, download_thread_func, (void *) &rank);
    if (r) {
        printf("Eroare la crearea thread-ului de download\n");
        exit(-1);
    }

    r = pthread_create(&upload_thread, NULL, upload_thread_func, (void *) &rank);
    if (r) {
        printf("Eroare la crearea thread-ului de upload\n");
        exit(-1);
    }

    r = pthread_join(download_thread, &status);
    if (r) {
        printf("Eroare la asteptarea thread-ului de download\n");
        exit(-1);
    }

    r = pthread_join(upload_thread, &status);
    if (r) {
        printf("Eroare la asteptarea thread-ului de upload\n");
        exit(-1);
    }
}
 
int main (int argc, char *argv[]) {
    int numtasks, rank;
 
    int provided;
    MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
    if (provided < MPI_THREAD_MULTIPLE) {
        fprintf(stderr, "MPI nu are suport pentru multi-threading\n");
        exit(-1);
    }
    MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    if (rank == TRACKER_RANK) {
        tracker(numtasks, rank);
    } else {
        peer(numtasks, rank);
    }

    MPI_Finalize();
}Generate code in c.Input files
Each client will have an input file named in<R>.txt (where R is the task rank), with the following format:
number_files_owned
name_fisier_detinut_1 number_segments_fisier_detinut_1
segment1_fisier_detinut_1
segment2_fisier_detinut_1
...
name_fisier_detinut_2 number_segments_fisier_detinut_2
segment1_fisier_detinut_2
segment2_fisier_detinut_2
...
number_fisiere_dorite
name_fisier_dorit_1
name_fisier_dorit_2
...
Thus, the first row contains the number of files owned by this client at the beginning of the program, followed by details about each file. For a file, the first row of details contains the name and number
of segments, and the following rows represent hashes (32 characters) of the file segments, in order (thus, the first row after the file name and size will contain the hash of the first segment of the file, and so on).
After the information about the files owned by a client, there is a row with the number of files that the client wants to download using BitTorrent, followed by the name of the desired files (one at a time).

Clients
As previously mentioned, the client, are all MPI tasks with rank higher than 0. As can be seen in the skeleton of the theme repository, a client has two threads of execution (implemented with
Pthreads), as follows:
• → thread <TAG1> this thread is used by the client to implement file download logic from seeds or peers and to achieve communication with the tracker
• → upload thread <TAG1> this execution thread is used to respond to segment requests that this customer owns, coming from other customers.
Initialising. At initialization, a client performs the following steps:
1. read the input file
2. tells the tracker what files it has (in other words, what files it is seed for)
• for each file, the client sends the hash to each segment in order
• so the tracker will know which files are in the network, how many segments they have, in what order they are, what hashes they have, and who owns them initially
3. Expects a response from the tracker that can start searching and downloading files that is interested.

Downloading. Once it has received confirmation from the tracker that it can continue, the client realizes the following steps:
1. asks the tracker for the list of seeds/peers for the files he wants (in other words, file swarms)
2. Look at the segments missing from the files you want, search the swarm from the tracker, and start sending requests to peers/seeds
3. For each segment of a desired file that it does not own, a client performs the following steps:
(a) look for a seed/peer that owns the segment sought
(b) send that seed/peer a request for the segment
(c) expect to receive the requested segment from seed/peer
(d) mark the segment as received
Attentiont! In order to receive the 20 points on efficiency (see the scoring section below), a customer must vary as much as possible the seed/node nodes/peer from which download the searched segments. With other
words, you do not want the download of a file to be done entirely from the same seed/peer.
Attentiont! Because it does not work with files themselves (but only with hashes of segments in a file), it will simulate downloading a segment of file from a seed/peer. This is enough as a customer
send a message to the seed/peer with the hash of the desired segment, and the/seed/peer to reply with a simple message like “ACK” or “OK” (it is at your discretion exactly how you approach this).

Updating. While a client is downloading a file, it is possible that another, and the client, is entering the swarm of that file, so it is necessary that occasionally, the tracker is consulted to update the client list, and from which a file can be downloaded. Thus, for this theme, a client performs the following steps after every 10 segments downloaded from seeds/peers:
1. asks the tracker for the updated list of seeds/peers for the files they want
2. resumes from step 2 of the Download section.
Receiving segment requests from other customers. When receiving a segment request from a peer, a customer first checks whether they own that segment. If he owns it, he's “send” to the peer the requested segment
(as specified above, this can be simulated by sending a message of type “ACK” or “OK”). If he does not own it, he sends the peer a negative answer (and he will look for the file elsewhere).
Completion download file. When you finish downloading all the segments of a file, a customer takes the following steps:
1. inform the tracker that it has all the file
2. Save the file (list of hashes in order) in an output file called client<R> <NUMEFISIER>
(where R is the rank of the client, and NUMEFISIER is the original name of the downloaded file); an example of the name for the file1 file downloaded by the client with rank 2 is client2 file1.
Finish download all files. When you finish downloading all the files you wanted, a customer realizes the following steps:
1. Sends the tracker a message informing him that he has completed all downloads
2. close the download execution thread (download thread), but leave it open on the upload one (upload thread), because it will still be able to act as a seed for the files it had and for the ones it downloaded.

Completion for all customers. When a client receives a message from the tracker that all customers have finished downloading their files, realize the following steps:
1. close the upload execution thread (upload thread)
2. closes altogether.

Tracker
The tracker maintains a list of files and the swarm associated with each of them. The swarm of a file contains the list of clients (seeds or peers) that have segments of that file, but not what segments each client has.
A segment is defined by a hash and its position in the file.
Initialising. At initialization, the tracker performs the following steps:
1. Wait for the initial message of each client, which will contain the list of owned files
2. For each file owned by a client, passes the respective client as seed in the file swarm
3. When received from all customers, respond to each with a “ACK” (sign that can start communication between customers to download the desired files).
Receiving messages from customers. When receiving a message from a customer, the tracker takes the following steps:
1. Look what kind of message he received
2. Depending on the type of message, perform one of the following actions:
• if the received message is a request from a client for a file (or an update request),
the tracker gives it the list of seeds/peers clients from swarm, and marks the client as a peer for that file (so it also adds it implicitly to the swarm of the file)
• if the received message is to complete a file download, the tracker marks that client as seed
• if the message received is to complete the download of all files by a client, the tracker marks the client as finished, but keeps it in the swarm of the files he owns (i.e
the ones he had originally or downloaded from other clients)
• if the message received means that all customers have finished downloading all the desired files, the tracker sends a message of completion to each client to tell them to stop,
and then he stops too.