ΙΑΣΟΝΑΣ ΚΑΡΑΠΡΟΔΡΟΜΙΔΗΣ SDI2200064
Σε αυτή την εργασία έπρεπε να υλοποιήσουμε ένα σύστημα συγχρονισμού αρχείων χρησιμοποιώντας sockets για την επικοινωνία μεταξύ διαφορετικών υπολογιστών. Το σύστημα αποτελείται από τρία βασικά προγράμματα:
Ο manager διαχειρίζεται τον αρχικό συγχρονισμό και την επικοινωνία με το console. Χρησιμοποιεί threads για τον παράλληλο συγχρονισμό αρχείων και έναν buffer, όπου τοποθετούνται προς επεξεργασία πληροφορίες όπως:
- η IP και το port των clients,
- το όνομα του αρχείου προς αντιγραφή,
- η διαδρομή προέλευσης και προορισμού.
Αποστέλλει εντολές στους clients για να γίνει η αντιγραφή, και κάθε ενέργεια που πραγματοποιείται από κάποιο thread καταγράφεται στο log file.
Ο client δέχεται εντολές από τον manager και εκτελεί ανάλογες ενέργειες:
LIST: επιστρέφει όλα τα αρχεία ενός directory,PULL: στέλνει το περιεχόμενο ενός αρχείου,PUSH: δημιουργεί ή ενημερώνει ένα αρχείο με βάση τα δεδομένα που λαμβάνει.
Ο client λειτουργεί ως server που ακούει σε συγκεκριμένο port για νέες εντολές.
Το console επιτρέπει στον χρήστη να δίνει εντολές για συγχρονισμό, ακύρωση, ή τερματισμό στο πρόγραμμα manager. Οι εντολές αποστέλλονται μέσω socket και οι απαντήσεις εμφανίζονται στην οθόνη και καταγράφονται στο αντίστοιχο log file.
Κατά την εκκίνηση, ο manager δημιουργεί τον buffer και εκκινεί όλα τα worker threads από την αρχή, ώστε να μπορούν όλες οι λειτουργίες να εκτελούνται παράλληλα χωρίς καθυστέρηση. Στη συνέχεια:
- Διαβάζει τις γραμμές του αρχείου
config. - Για κάθε γραμμή, στέλνει μια εντολή
LISTστον client. - Τοποθετεί όλα τα αρχεία του αντίστοιχου directory στον buffer για συγχρονισμό.
Αφού ολοκληρωθεί ο αρχικός συγχρονισμός, ο manager:
-
Ανοίγει το socket στο οποίο θα ακούει για εντολές από το console.
-
Όταν λάβει την εντολή
add, στέλνειLISTστον source client και τοποθετεί τα αρχεία στον buffer για συγχρονισμό. -
Όταν λάβει την εντολή
cancel, αφαιρεί όλα τα αρχεία του αντίστοιχου directory από τον buffer (μέσω τηςremove_all_syncing). -
Όταν λάβει την εντολή
shutdown, βάζει στον buffer ειδικά "μηνύματα τερματισμού" (με port = -1). Τα worker threads που θα τα διαβάσουν, κάνουν exit. Το main πρόγραμμα περιμένει μεjoinόλα τα threads να τερματίσουν. Μετά:- Στέλνει απάντηση στο console για να τερματίσει.
- Κλείνει όλα τα αρχεία και sockets.
- Τερματίζει.
Ο buffer λειτουργεί ως ουρά: οι ενέργειες συγχρονισμού ολοκληρώνονται με τη σειρά πριν γίνει shutdown.
Κάθε worker thread:
- Κάνει
popαπό τον buffer. - Αν λάβει
return -1, τερματίζει. - Συνδέεται στον client μέσω της IP και του port που έλαβε από τον buffer.
- Στέλνει
PULLγια να κατεβάσει το αρχείο. - Στέλνει
PUSH -1στον target client για να δημιουργηθεί το αρχείο. - Στέλνει τα δεδομένα σε chunks.
- Στέλνει
PUSH 0για να κλείσει το αρχείο και τη σύνδεση. - Κλείνει sockets και κάνει log για τις ενέργειες
PULLκαιPUSH.
Το log για το PULL γίνεται στο τέλος για να διασφαλιστεί ότι δεν υπήρξε σφάλμα.
Ο buffer είναι μια ουρά υλοποιημένη με συνδεδεμένη λίστα και έχει δύο βασικές λειτουργίες: push και pop. Για τον συγχρονισμό, χρησιμοποιούνται mutex και condition variables:
-
Στο
push:- Αν η ουρά είναι γεμάτη, το thread μπλοκάρεται.
- Αν ήταν άδεια πριν, γίνεται
signalγια να ξυπνήσουν τα threads που περιμένουνpop.
-
Στο
pop:- Αν η ουρά είναι άδεια, το thread περιμένει.
- Όταν αφαιρείται στοιχείο, γίνεται
signal.
Ο buffer κρατά:
- Το αρχείο προς συγχρονισμό
- Την IP και το port του source client
- Το directory και το όνομα του αρχείου στον target client
- Την IP και το port του target client
Επιπλέον λειτουργίες:
remove_all_syncing(directory): Αφαιρεί όλα τα αρχεία προς συγχρονισμό του συγκεκριμένου directory (για τηνcancel).is_syncing(directory): Επιστρέφει αν ένα directory είναι προς συγχρονισμό αυτή τη στιγμή.
Το console:
- Ανοίγει το logfile του.
- Συνδέεται στο socket του manager (μέσω των arguments).
- Διαβάζει από το
stdinκαι στέλνει εντολές στον manager. - Εκτυπώνει τις απαντήσεις στο
stdout. - Όταν δοθεί
shutdown, περιμένει την απάντηση από τον manager και τερματίζει.
Ο client:
- Εκκινεί με όρισμα το port στο οποίο θα ακούει.
- Περιμένει για συνδέσεις.
- Ανάλογα με την εντολή:
LIST: Ανοίγει το directory (αν υπάρχει), στέλνει τα ονόματα των αρχείων, και στο τέλος μια τελεία.για ολοκλήρωση.PULL: Στέλνει πρώτα το μέγεθος του αρχείου και έπειτα το περιεχόμενο σε chunks.PUSH:- Αν λάβει chunk size
-1, δημιουργεί το αρχείο. - Αν λάβει chunk size
> 0, κάνει append. - Αν λάβει chunk size
0, κλείνει το αρχείο και περιμένει νέα σύνδεση.
- Αν λάβει chunk size
Για να γινουν compile ολα τα αρχεια:
make Αυτό:
- Δημιουργεί φακέλους
ObjectFiles,LogFilesαν δεν υπάρχουν. Για να γινει compile μονο ο manager:
make managerΓια να γινει compile μονο ο client:
make clientΓια να γινει compile μονο το console:
make consoleΓια να καθαρίσουμε τα object files και τα εκτελέσιμα, εκτελούμε:
make cleanΑυτό διαγράφει:
- Όλα τα
.oαρχεία στον φάκελοObjectFiles - Τα εκτελέσιμα αρχεία
nfs_manager,nfs_console,nfs_client - Και τον φάκελο
ObjectFilesαν είναι άδειος.
Για να τρεξει ο manager:
./nfs_manager -l <logfile> -c <configfile> -n <worker_limit> -p <port> -b <buffer_size>ΣΗΜΕΙΩΣΗ: Αν δεν δωθει worker limit το default limit ειναι 5.
Για να τρεξει ο client:
./nfs_client -p <port> Για να τρεξει το console:
./nfs_console -l <console-logfile> -h <host_ip> -p <host_port> ΣΗΜΕΙΩΣΗ: Για να τρεξει το console πρεπει να ειναι ηδη ανοιχτος ο manager.