Στο συγκεκριμένο φάκελο, περιλαμβάνεται τα εξής:
- Ένα απλό makefile (πατώντας
make, κάνουμε compile όλα τα απαραίτητα προγράμματα, ενώ μεmake cleanμπορούμε να διαγράψουμε τα αντικείμενα αρχεία που δημιουργήσαμε). - Ο φάκελος
Modules, περιλαμβάνει όλα τα .c αρχεία (τρία από αυτά βρίσκονται μέσα στο folderfss_manager) - Ο φάκελος
Includes, περιλαμβάνει όλα τα .h αρχεία
Εκτέλεση:
Για να εκτελέσουμε το πρόγραμμα πατάμε make, και στη συνέχεια ./fss_manager -l <manager_logfile> -c <config_file> -n <worker_limit> (όπου το -n είναι optional και αν δεν δοθεί ή δοθεί όχι θετικός αριθμός τίθεται σε 0).
Ο "fss_manager" μπορεί να τρέξει ανεξάρτητα του "fss_console", αν θελήσουμε να τον τρέξουμε όμως (πατώντας ./fss_console -l <console-logfile>) επιτυγχάνετε σωστά και ομαλά η επικοινωνία μεταξύ "fss_manager" - "fss_console".
Ο "worker" καλείτε από τον "fss_manager" για οποιαδήποτε εργασία τον χρειαστεί, αλλά μπορούμε να τον τρέξουμε και αυτόνομα αν θελήσουμε (πατώντας ./worker <SOURCE_DIR> <TARGET_DIR> <FILE_NAME> ).
Τρόπος Υλοποίησης:
- fss_manager:
Απαρτίζεται από τα αρχεία του φακέλου fss_manager (μέσα στο Modules) και τα header του φακέλου Includes.
- fss_manager.c: είναι το κύριο αρχείο το οποίο εκτελεί την
main(), είναι υπεύθυνος για την ανάγνωση από το confing_file και την αποθήκευση των πληροφοριών του, την επικοινωνία "fss_manager"-"fss_console" και εκκίνηση worker και παραλαβή exec_report, αλλά και την σωστή παρατήρηση αλλαγών στα διάφορα αρχεία με την χρήσηinotify(). - manager_utils.c/h: για να πετύχει τα παραπάνω ο
fss_managerκάνει χρήση των συναρτήσεων τουmanager_utils.c. Έχει τις συναρτήσεις για έναρξη και ομαλή/σωστή λήξη ενόςworkerαλλά και τις βοηθητικές συναρτήσεις για εγγραφή στο logfile. - sync_info_mem_store.c/h: έχει όλες τις δομές και συναρτήσεις των δομών που χρειάζεται ο
fss_manager. Η sync_info είναι η κύρια δομή, στη οποία αποθηκεύονται τα δεδομένα των directories. Η ActiveWorker είναι η δομή που κρατάει ποίος είναι οworkerπου ανέλαβε μια διεργασία(task), όπως και το ποιανού directory ήταν το task. Ενώ η WaitingQueue είναι μια δομή που αποτελείτε από κόμβους WaitingPair. Κάθε κόμβος της, φέρει τις πληροφορίες για κάποια διεργασία και αυτή τους βάζει στη σειρά να περιμένουν κάποιον worker τα εκτελέσει τα "tasks τους". Εκεί αρχικοποιείται και η global λίσταsync_info_list, η οποία χρησιμοποιείτε και κατευθείαν από τοfss_manager.cγια άμεση πρόσβαση στο head της λίστας και ορθή εισαγωγή στοιχείων στη δομή.
- fss_console:
Απαρτίζεται από το fss_console.c.
-
fss_console.c: εκτελεί όλες τις λειτουργίες για αποστολή και λήψη εντολών και μηνυμάτων προς και από τον
fss_manager. Πριν στείλει κάποια εντολή, ελέγχει αν το "format" της εντολής είναι αποδεκτό, και έπειτα την στέλνει. Από εκεί και στο εξής αν προκύψει κάποιο λάθος, θα το εντοπίσει οfss_manager. Έπειτα αναμένει να πάρει απάντηση από τονfss_managerμε το αποτέλεσμα της εντολής, το καταγραφεί στο logfile του (ο fss_console) και είναι πάλι έτοιμος να καταχωρίσει νέα εντολή. -
Σημείωση 1): δεν καταγράφετε κάποιο μήνυμα πουθενά στη περίπτωση που τρέξουμε την εντολή
sync <directory>με μη έγκυρο<directory> -
Σημείωση 2): το buffer για την ανάγνωση μηνυμάτων από τον
fss_managerείναι μεγέθους 256 χαρακτήρων. Αυτό γιατί έκρινα πως είναι ενα ιδανικό νούμερο αφού είναι τόσο μεγάλο όσο χρειάζεται για να διαβάσει με ένα read() όλο το μήνυμα(άρα αποφυγή του μεγάλου overhead, π.χ. στη περίπτωση που διάβαζε την απάντηση χαρακτήρα-χαρακτήρα), τις περισσότερες φορές και να μην δεσμεύσει μια πολυ μεγάλη στατική μνήμη που δεν θα χρησιμοποιήσει. Σε περίπτωση που δεν χωρέσει το μήνυμα με ενα read(), ξανά διαβάζει όσες φορές και αν χρειαστεί, μέχρι να βρεθεί ο χαρακτήρας '\0'.
- worker:
Απαρτίζεται από το worker.c.
- worker.c: εργάζεται πάνω στα tasks που θα του στείλει ο 'fss_manager' και γυρνάει exec_report με structured output πίσω στον 'fss_manager'. Η δομή του exec_report είναι η εξής:
[RESULT] [DETAILS]\n
ERRORS:\n[ERRORS BUFFER]
όπου το [RESULT] έχει τιμές SUCCESS, ERROR, ή PARTIAL. Το [DETAILS] παίρνει τιμή ανάλογα το operation. Αν είναι 'FULL' αναγράφει πόσα files έκανε copy, skip ή και τα δύο, ενώ σε οποιαδήποτε άλλη περίπτωση, γράφει "File: <directory_name>" και αν ήταν το [RESULT] ERROR, έπειτα από μια παύλα ('-') αναγράφει και το ERROR που γύρισε η "strerror(errno)". Η γραμμή ERRORS:\n[ERRORS BUFFER] υπάρχει μόνο στη περίπτωση του operation == "FULL" και το [ERRORS BUFFER] φέρει όλα τα μηνύματα που προέκυψαν από κάποιο λάθος στα διάφορα files που προσπάθησε να αντιγράψει ο worker.
- Σημείωση 3): Το
ERRORS:\n[ERRORS BUFFER]δεν έχει κάποιον πρακτικό ρόλο σε ότι αφορά την σωστή μεταφορά των πληροφοριών του exec_report στοfss_manager, αλλά υπάρχει μόνο για να δείχνει τα μηνύματα σε περίπτωση που κάποιος θέλει να εκτελέσει το./workerαυτόνομα, ώστε να του δίνει την πλήρης εικόνα όλων των πολλαπλών σφαλμάτων(πολλαπλά error μηνύματα μπορούμε να έχουμε μόνο στο "FULL" operation, αφού σε άλλη περίπτωση, με ένα λάθος κατευθείαν τερματίζει η αντίστοιχη εργασία του worker).
- fss_script.sh: το bash ανιχνεύει αν είναι έγκυρο το input και αν είναι όντως εκτελεί το αντίστοιχο command. Σε περίπτωση κάποιου λάθους path, απλά δεν θα κάνει κάτι print(/δεν εκτελεί κάποια ενέργεια) αλλιώς για οποιαδήποτε άλλο λάθος Input ειδοποιεί και τον χρήστη.
Τέλος, να αναφέρω πώς σε όλο τον κώδικα υπάρχουν παντού αναλυτικά σχόλια με περισσότερες λεπτομέρειες για την κάθε μια λειτουργία.
Σας ευχαριστώ πάρα πολύ για τον χρόνο που αφιερώσατε!