makotora / Syspro-MirrorServer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

---Προγραμματισμός Συστήματος - Εαρινό εξάμηνο 2017 - Project 3---
 _____________________
|---Μανούσος Τοράκης--|
|---1115 2014 00201---|
|_____________________|

|Σημαντικά|
>Έχω υλοποιήσει όλα τα ζητούμενα τις εργασίας
>Δεν έχω memory leaks (έχω τρέξει valgrind).
>Δεν έχω busy waiting
>Υπάρχει Makefile που δημιουργεί όλα τα εκτελέσιμα, τα οποία καλούνται όπως ζητείται απο εκφώνηση
>Bonus!
===>Έχω κάνει το BONUS!
Ουσιαστικα στο παραδοτέο έχω αφήσει και το βασικό σκέλος της εργασίας το οποίο αποτελούν ΟΛΑ τα αρχεία ΕΚΤΟΣ του GeneralServer.c

Για το bonus, το αρχείο GeneralServer.c αντικαθιστα ουσιαστικά τα MirrorServer.c και ContentServer.c καθώς
εμπεριέχει τις λειτουργίες και των 2 προηγούμενων. Ο Initiator είναι ο ίδιος με πρίν!
Δηλαδή, είναι σε θέση να λειτουργήσει και ως MirrorServer και ως ContentServer, ταυτόχρονα!
Προσοχή στα define KILL_CONTENT_SERVERS και KEEP_RUNNING (εξηγώ παρακάτω στα DEFINES)

Για την κλήση του 'bonus' GeneralServer: 
	./GeneralServer -p <port> -d <dirorfilename> -m <dirname> -w <threadnum>

Με λίγα λόγια, ο τρόπος που λειτουργεί ο GeneralServer είναι να απαντάει σε requests όπως θα έκανε ο Content.
Απλά πρόσθεσα επιπλέον στα LIST και FETCH requests, το SOR (Start Of Requests) request.
Αυτό το στέλνει για έναρξη επικοινωνίας ο Initiator, μετά τα requests και τέλος EOR (End Of Requests)
Έτσι, ουσιαστικά ο GeneralServer απαντάει στο SOR request, κάνοντας ότι θα έκανε και ο MirrorServer.
Ο GeneralServer,σε αντίθεση με τον MirrorServer δεν κάνει handle πάνω απο έναν Initiator ταυτόχρονα.
Αν του στείλουν πολλοί συγχρόνως, απαντάει στους 'extra' Initiators να δοκιμάσουν αργότερα.

>Στον ContentServer χρησιμοποιώ threads για να διαχειρίζομαι πολλαπλά requests

>Πρόσθεσα και στην FETCH request ένα ID,που είναι το ίδιο με το οποίο έγινε το LIST (μπαίνει στον buffer)
Τα threads του contentServer κρατάνε μια λίστα απο ID και delay για καθένα απο αυτά (συγχρονισμός με mtx)

>Η απάντηση στο LIST έχει 2 σκέλη.Πρώτα στέλνονται οι κατάλογοι που έχει ο content και μετά τα αρχεία.
Η ιεραρχία των καταλόγων δημιουργείται ενώ λαμβάνεται η απάντηση για το LIST (δεν μπαίνουν directories στον buffer)
Για τον έλεγχο αν ο MirrorServer "θέλει" (με βάση το request) ένα directory (για να κάνει mkdir)
ή ένα αρχείο (για να μπει στον buffer) έφτιαξα την συνάρτηση matchesDirOrFile (είναι στο functions.c)

>O MirrorServer Server όπως αναφέρω παραπάνω, μπορεί να απαντήσει σε πολλούς Initiator ταυτόχρονα (κάνει fork τον εαυτό του, και το παιδί του κάνει τα υπόλοιπα δημιουργώντας mirror,worker threads buffer etc).

>Fetching
Για την μεταφορά αρχείων έχω φτιάξει ειδικές συναρτήσης sendFile Και receiveFile (στο Protocol.c) όπου ακολουθώ ένα συγκεκριμένο πρωτόκολλο μεταφοράς (με απάντηση επιβεβαίωσης κλπ)

>Structs
Διάφορες δομές που χρησιμοποιώ (κυρίως λίστες απο πράγματα) περιγράφονται στα structs.c structs.h
Για τον κοινό buffer έφτιαξα τα αρχεία buffer.c buffer.h για λόγους οργάνωσης κώδικα.

|DEFINES - OPTIONS|
Στα βασικά αρχεία (MirrorServer ContentServer GeneralServer)
Υπάρχουν ορισμένα defines που αποτελούν options για τον τρόπο εκτέλεσής τους:

PRINTS: Το χω αφήσει 0.Αν είναι 1 εκτυπώνεται με αρκετή λεπτομέρεια το τι γίνεται κατά την εκτέλεση.Κυρίως για debug και για επιδειξη.

PRINTS2: Το χω αφήσει 1.Αν είναι 1 εκτυπώνονται ορισμένα μόνο βασικά πράγματα για την πορεία της εκτέλεσης (Fetches Stats etc)

KILL_CONTENT_SERVERS : Το έχω αφήσει 1. 
Αν είναι 1, ο MirrorServer ή ο GeneralServer στέλνουν μήνυμα τερματισμού στους ΔΙΑΚΡΙΤΟΥΣ ContentServer που συμμετείχαν στα requests που στάλθηκαν απ τον Initiator ΑΦΟΥ τελείωσει με αυτούς.Το άφησα 1 επειδή αυτό κατάλαβα ότι έπρεπε απ το piazza.Αν γίνει 0 τότε δεν στέλνει μήνυμα τερματισμού.

KEEP_RUNNING: Το έχω αφήσει 0.
Αν είναι 1, ο MirrorServer ή ο GeneralServer συνεχίζουν να τρέχουν και να δέχονται άλλα requests μέχρι κάποιος (έχω πρόγραμμα και γι αυτό, μιλάω παρακάτω) τους πει να τερματίσουν.
Διαφορετικά αν είναι 0, τερματίζουν άφού απαντήσουν σε ΕΝΑΝ Initiator.

MAX_RECONNECTS: Το έχω αφήσει 100.
<!> Disclaimer! Γενικά λειτουργεί και χωρίς αυτό! Αν θέλετε βάλτε το 0 θα δουλεύει και πάλι!
Κάποιες φορές (πολύ σπάνια), είχα errors στην connect στον υπολογιστή μου (οχι στα Linux της σχολής).Θεωρώ ότι είναι καλή πρακτική γενικά να δοκιμάζεις ξανά το connect κάποιες φορές αντί να τερματίζεις κατευθείαν.Οπότε αυτό που κάνω είναι ότι δοκιμάζω να κάνω connect άλλες MAX_RECONNECTS φορές,με καινούργια socket (Κλείνοντας την προηγούμενη) κάθε φορά, αν φυσικά αποτύχει η connect (Αν πετύχει σταματάω το loop)!


>>Τερματισμός
Οι servers μου (Content Mirror General) μπορούν να δεχτούν έναν δικό μου τύπο request, τον KYS (Kill Your Self).
Αυτόν τον τύπο request χρησιμοποιεί για παράδειγμα ο MirrorServer (ή και ο GeneralServer) για να "τερματίσει" τους ContentServer.

Το ίδιο όμως request δέχεται και ο ίδιος ο MirrorServer Και ο GeneralServer! Αυτό έχει νοήμα αν το define KEEP_RUNNING είναι 1, ώστε να μπορεί, ακόμα και απομακρυσμένα, να δεχτεί εντολή "φυσιολογικού" τερματισμού.
Για να μπορούμε όμως να στείλουμε ένα τέτοιο request σε οποιονδήποτε Server έφτιαξα το πρόγραμμα killServers.
Αυτό έχει ένα πολύ απλό CLI όπου γράφεις 'host_name:port' και στέλνει απλώς "KYS" στον αντίστοιχο server.
Τo killServers τερματίζει με 'exit'.

About


Languages

Language:C 98.2%Language:Makefile 1.8%