-
Notifications
You must be signed in to change notification settings - Fork 0
demetresalx/SysproAssign2
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
# 2nd System Programming Assignment 2020 **D. Alexandres, 1115201400006.** Second (2nd) assignment on UNIX system programming, *University of Athens, 2020.* Υλοποιήθηκε με C++ σε Ubuntu 16.04 LTS και δοκιμάστηκε σε μηχάνημα της σχολής. Όλα τα ερωτήματα/εντολές έχουν υλοποιηθεί. -----C++ ΚΟΜΜΑΤΙ--------- #ENTOLH METAGLWTTISHS make #ENTOLH EKTELSHS Ίδια με της εκφώνησης (ή make run αν επιθυμεί ο χρήστης να ορίσει παραμέτρους στο makefile και να το τρέχει απο κει) Παρακαλώ οι ηλικίες των εγγραφών στα διάφορα αρχεία να είναι αριθμοί για να μην υπάρξουν προβλήματα με την stoi. Χρησιμοποιήθηκαν ως επί το πλείστον οι δομές της εργασίας 1. Περιλαμβάνουν έναν HT βάσει ID για τις εγγραφές και τους disease&country HTs. Υπάρχουν και οι ενδιάμεσες δομές που χρησιμοποιούσα στην άσκηση 1 που έχουν μείνει οι περισσότερες ως ήταν. (π.χ. ο σωρός για topk). Ιδιαίτερη ανάλυσή τους δε θα γίνει εδώ (υπάρχουν σχόλια στον κώδικα και όλα στο readme της 1ης άσκησης). ΔΟΚΙΜΑΣΤΗΚΕ ΜΕ VALGRIND ΚΑΙ ΔΕΝ ΕΧΕΙ LEAKS (βλέπε παρακάτω για SIGKILL). ------ΠΡΩΤΟKΟΛΛΟ ΕΠΙΚΟΙΝΩΝΙΑΣ PIPES------ Χρησιμοποιώ blocking pipes. Τα ανοίγω μια φορά στην αρχή και κρατώ τους descriptors όπως προτάθηκε στο piazza. Όλη η γραφή σε/ανάνγωση από ta named pipes γίνεται στη βάση του εξής πρωτοκόλλου: Πρώτα ο writer στέλνει έναν ακέραιο που είναι το ακριβές μέγεθος του μηνύματος που σκοπεύει να στείλει. Έπειτα o reader διαβάζει τον ακέραιο για να ξέρει πόσα bytes πρέπει να διαβάσει. Ακολουθεί μια while loop που χειρίζεται τις περιπτώσεις των read/write και σιγουρεύεται οτι θα διαβάζονται/γράφονται το πολύ bufferSize bytes τη φορά (όρισμα άσκησης). POLL : Στις ερωτήσεις-απαντήσεις μεταξύ γονέα-παιδιών χρησιμοποιείται η poll() για τη συντομότερη σύνθεση της απάντησης. Ακόμη και σε ερωτήματα που αφορούν σε μια χώρα (που την έχει μόνο ένα παιδί), επειδή σκόπιμα ρωτάω όλους τους workers (για να καλυψω και την περίπτωση που προστεθεί φάκελος υπάρχουσας χώρας σε άλλο παιδι) η poll() εξασφαλιζει οτι θα διαβαστουν πολυ γρηγορα τα 0 που θα επιστρεψουν αυτοι που δε θα βρουν τη χωρα και μετα θα εμφανισει τα αποτελεσματα που θα ειναι ετοιμα. Η χρήση της poll βασίζεται σε παράδειγμα στη σελίδα του κ. Δελή. Οι συναρτήσεις send_string, receive_string που έχω υλοποιήσει απλώς στο τέλος γράφουν το αποτέλεσμα σε ενα std::string της c++ για δική μου χρήση. Σε επίπεδο pipes ασφαλώς η ανάγνωση γίνεται με char* (δε γίνεται κ αλλιώς). -Οι υλοποιήσεις αυτές βασίζονται στις readall, writeall του βιβλίου Marc J. Rochkind - Advanced UNIX Programming (2004, Addison-Wesley Professional). (η αμερικάνικη βερσιον που βρήκα στο ιντερνετ, κανονικό βιβλίο δεν έχω πάρει). ------SIGNALS------ Θα ήταν επιθυμητό να δοκιμαστεί πρώτα μια φορά η άσκηση χωρίς τα signals. Έχουν υλοποιηθεί τα SIGINT/SIGQUIT σε γονιο και παιδί. https://piazza.com/class/k6pgj1tl3da50l?cid=197 Για σήματα στους workers : "μπορείτε να θεωρείστε δεδομένο ότι θα χει ολοκληρωθεί η όλη διαδικασία της κατασκευής & αποστολής των statistics." Οι περιτπώσεις των SIGINT/SIGQUIT έχουν υλοποιηθεί ως ζητούνται. Δηλαδή εάν το παιδί δεχτεί SIGINT/QUIT τότε θα τερματίσει ομαλά και πριν το κάνει θα δημιουργήσει το logfile του. Αν ο γονιός δεχτεί SIGINT/SIGQUIT τότε θα σταματήσει, θα στείλει SIGKILL στα παιδιά του, θα τα περιμένει να τελειώσουν και μετά θα γράψει το logfile του και θα τερματίσει και αυτός ομαλά. Να σημειωθεί ότι στην περίπτωση του SIGINT στο γονιό, θα σταλεί SIGKILL στα παιδιά (όπως ζητείεται) οπότε μπορεί να μην προλάβει να φτιάξει logfile το παιδί. Ο γονιός όμως θα το φτιάξει όπως ζητείται. ΔΕ ΔΙΑΚΟΠΤΩ μια εντολή κατά τη διάρκεια της εξέλιξής της. Αυτό το πετυχαίνω με τη sigprocmask τόσο στο γονιό όσο και στα παιδιά την ώρα που εκτελείται μια εντολή. Με τη sigpromask ξεμπλοκάρω τα σήματα ώστε να παραδοθούν τα pending, αφού τελειώσει η τρέχουσα εντολή. Έχει ειπωθεί στο piazza πως αυτό είναι αποδεκτό. ------ΣΗΜΑΝΤΙΚΕΣ ΔΙΕΥΚΡΙΝΙΣΕΙΣ ΚΑΙ ΠΑΡΑΔΟΧΕΣ------ Ο ρόλος του aggregator είναι ουσιαστικά μια διεπαφή χρήστη https://piazza.com/class/k6pgj1tl3da50l?cid=211 (ΣΩΣΤΗ ΚΑΙ ΑΠΟΔΕΚΤΗ ΠΡΟΣΕΓΓΙΣΗ) Τα summary statistics ομως εχουν φτιαχτει κανονικά. Τα namedpipes ανοίγουν μια φορά στην αρχή και κρατάω τα fds. Κλείνουν στο τέλος του προγράμματος, όπως ειπώθηκε στο piazza. Μόλις ο aggregator προωθήσει μια εντολή στους workers, διαβάζει τις απαντήσεις μέσω ενός πρωτοκόλλου ώστε να ξέρει πόσες παραμέτρους να περιμένει. Τα summaries που επιστρέφουν οι workers στον πατέρα μετά το διάβασμα των αρχείων τους διαβάζονται και εκτυπώνονται από αυτόν με POLL(). Έτσι, δε χρειάζεται ο γονιός να περιμένει ένα παιδί που δεν έχει τελειώσει ακόμα το parsing του για να εκτυπώσει τα διαθέσιμα summaries άλλων παιδιών. Εδώ να σημειωθεί ότι αν υπάρχουν προβληματικές εγγραφές στα αρχεία, επειδή τα παιδιά εκτυπώνουν ERROR σε αυτή την περίπτωση γίνεται σε περίπτωση που ένα παιδί ακόμα κάνει parsing ενώ για ένα άλλο που έχει τελειώσει ο γονιός να εκτυπώνει τα summaries του, να εκτυπώσει το αργό παιδί κάπου ενδιάμεσα τη λέξη ERROR - το οποίο είναι και απολύτως φυσιολογικό δεδομένου οτι στο τερμιναλ το stdout ταυτιζεται με το stderr -. Το διευκρινίζω απλώς ώστε να μην υπάρξουν παρεξηγήσεις με κανένα "script". Η καλύτερη εκτύπωση των summaries θα ήταν με dataset χωρίς προβληματικές εγγραφές, αν και όπως είπα είναι φυσιολογικό να συμβεί. ΤΟ ξαναγράφω εδώ : όλη η δεσμευμένη μνήμη αποδεσμεύεται μέσω των άρτιων destructors της c++ που έχω φτιάξει. Όταν ένας worker τερματίσει χωρίς sigkill (μέσω sigint π.χ.) η εμβέλεια των τοπικών μεταβλητών "records_htable", "diseases_htable", countries_htable θα τελειώσει και θα κληθούν οι destructors τους. Αυτοί φροντίζουν για την αποδέσμευση όλου του δυναμικού χώρου που κρατήθηκε για τις ανάγκες της άσκησης. Στην περίπτωση όμως της exit και του sigint/quit στο γονέα, αυτό δε είναι 100% οτι θα συμβεί καθώς τότε το παιδί θα δεχτεί SIGKILL. Έχει ειπωθεί στο piazza ότι δεν υπάρχει απαίτηση στην περίπτωση του sigkill. Ωστόσο ο κώδικας μου κάνει την απαιτούμενη αποδέσμευση, όπως θα έπρεπε. ΣΗΜΑΝΤΙΚΟ: για τα ορίσματα date1 date2 ακολουθείται η προσέγγιση που είχα ακολουθήσει και στην άσκηση 1 και είχε προτείνει τότε βοηθός και είναι η : "να βρεις τα records στα οποία το entry date είναι μικρότερο από το date2. Στην συνέχεια για όσα records έκαναν qualify πετάς όσα το exit date είναι μικρότερο από το date1". Επίσης δε μπορεί να δοθεί - ως όρισμα ενός date γιατί η εκφώνηση λέει αν είναι το ένα ορισμένο πρέπει να είναι και το άλλο. -ΓΙΑ /numPatientDischarges : καταλαβαίνω το "που έχουν βγει από το νοσοκομείο στη συγκεκριμένη χώρα μέσα στο διάστημα [ date1 date2]" ως "το exitdate ανηκει στο διαστημα [date1, date2]". Η λέξη Discharge (δλδ η έξοδος και όχι η απουσία) ενισχύει περισσότερο αυτή μου την αντίληψη. -H diseaseFrequency είναι όμοια με της 1ης άσκησης. -----BASH-------- #ENTOLH EKTELSHS Ίδια με αυτή που αναφέρει η εκφώνηση για το bash script. Παρακαλώ θερμά να γίνεται σεβαστή η σειρά των ορισμάτων. Ο κώδικας του σκριπτ εχει αρκετά σχόλια που ξεκαθαρίζουν πως ακριβώς λειτουργεί και με ποια λογική. Κατα τη δημιουργια εγγραφών, δεδομενου οτι οι ENTER καλο θα ηταν να ειναι περισσοτερες των EXIT, εχω δωσει 80% πιθανοτητα για ENTER και 20% για EXIT. EXIT εγγραφές προκύτπουν από εγγραφές που έχουν γίνει ENTER νωρίτερα (εντός ίδιας χώρας φυσικά) Όπως ειπώθηκε στο piazza https://piazza.com/class/k6pgj1tl3da50l?cid=137, είναι φυσιολογικό το dataset που προκύπτει να έχει errors Στη δική μου περίπτωση αυτά είναι κατά το δυνατόν ελαχιστοποιημένα. Το ID των εγγραφών προκύπτει από ενα τυχαιο γραμμα + τα index καθε λουπας επαναληψης τους(μοναδικος συνδυασμος) ωστε να ειναι μοναδικο για καθε εγγραφη Αυτό απαλοίφει και την πιθανότητα διπλότυπου ID σε άλλη χώρα. Τα ids που παράγει το σκριπτ μου ειναι ΜΟΝΑΔΙΚΑ.
About
Second assignment for Systems Programming
Resources
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published