Επισκόπηση Κατανεµηµένα Συστήµατα Ι Μάθηµα Βασικής Επιλογής, Χειµερινού Εξαµήνου Τοµέας Εφαρµογών και Θεµελιώσεων Χρήστος Κονίνης Ορέστης Ακριβόπουλος Τρίτη, 2 Νοεµβρίου 2010 Υπολογιστικό Examples Πώς ϕτιάχνουµε µια νέα διεργασία στο shawn Πώς εισάγουµε ένα template processor στο shawn The Processor The Messages Simulation Commands Simulation Commands Για να εκτελέσουµε µια εξοµοίωση πρέπει να δώσουµε στο shawn ένα σύνολο από εντολές Τις εντολές αυτές συνήθως τις γράφουµε σε ένα αρχείο µε κατάληξη.conf (π.χ. hello.conf) στο ϕάκελο shawn/buildfiles Και για να τις εκτελέσουµε δίνουµε την εντολή στο ίδιο ϕάκελο:./shawn -f hello.conf Παράδειγµα ενός hello.conf prepare_world edge_model= simple comm_model= disk_ graph range=1 r e c t _ w o r l d width =5 height =5 count =30 p r o c e s s o r s = h e l l o w o r l d Οι εντολές αποτελούνται από το όνοµα της εντολής ακολουθούµενο από µια σειρά από παραµέτρους, π.χ.: command_name parameter=<value> parameter=<value>... 1. Η εντολή prepare_world δηµιουργεί ένα νέο περιβάλλον εξοµοίωσης: prepare_world edge_model=simple comm_model=disk_graph range=1 2. Η εντολή rect_world κατασκευάζει µια παραλληλόγραµµη περιοχή και τοποθετεί τυχαία κόµβους και τους ϑέτει την διεργασία helloworld: rect_world width=5 height=5 count=50 processors=helloworld 3. Η εντολή simulation εκκινεί την εξοµοίωση µε µέγιστο αριθµό γύρων(iterations) : simulation max_iterations=50
Simulation Commands 1. Η εντολή save_world αποθηκεύει την τρέχουσα τοπολογία(γράφο δικτύου) στο αρχείο που δίνετε από την παράµετρο file: save_world file=topology.xml snapshot=0 2. Η εντολή load_world ϕορτώνει τις ϑέσεις των κόµβων από µια αποθηκευµένη τοπολογία και τους ϑέτει την διεργασία helloworld: load_world file=topology.xml processors=helloworld Την χρησιµοποιούµε όταν έχουµε ένα αντίστοιχο αρχείο αντί της εντολής rect_world 1. Ανοίγουµε ένα αρχείο hello.conf στον ϕάκελο shawn/buildfiles και γράφουµε τις παρακάτω εντολές: prepare_world edge_model= simple comm_model= disk_ graph range=1 r e c t _ w o r l d width =5 height =5 count =30 p r o c e s s o r s = h e l l o w o r l d save_world f i l e = topology. xml snapshot =0 2. Ανοίγουµε µια κονσόλα στον ϕάκελο shawn/buildfiles 3. Εκτελούµε την εντολή:./shawn -f hello.conf Επισκόπηση Επαναλαµβάνουµε τα ϐήµατα 1 ως 3 αλλάζοντας το hello.conf σε : prepare_world edge_model= simple comm_model= disk_ graph range=1 # r e c t _ w o r l d width =5 height =5 count =30 p r o c e s s o r s = h e l l o w o r l d # save_world f i l e = topology. xml snapshot =0 load_world f i l e = topology. xml p r o c e s s o r s = h e l l o w o r l d Examples Πώς ϕτιάχνουµε µια νέα διεργασία στο shawn Πώς εισάγουµε ένα template processor στο shawn The Processor The Messages
Transmission model Μέχρι τώρα κατασκευάζαµε ένα simulation world µε την εντολή: prepare_world edge_model=simple comm_model=disk_graph range=1 Στην οποία αν και δεν δηλώνεται, το transmission model είναι το reliable, δηλαδή όλα τα µηνύµατα αποστέλνονται µε επιτυχία και χωρίς καθυστερήσεις prepare_world edge_model=simple comm_model=disk_graph transm_model=reliable range=1 Γενικά µπορούµε να χρησιµοποιήσουµε πολλαπλά transmission models και κάθε µήνυµα που αποστέλνεται περνάει από κάθε transmission model πριν παραδοθεί στους τελικούς παραλήπτες Message -> ChainTransModel1 -> ChainTransModel2 -> EndTransModel Αν ϑέλουµε ο shawn να κρατάει στατιστικά για τον αριθµό των µηνυµάτων που στάλθηκαν σε µια εξοµοίωση, χρησιµοποιούµε το stats_chain µοντέλο prepare_world edge_model= l i s t comm_model= disk_ graph \ transm_model= s t a t s _ c h a i n \ range=1 chain_transm_model name= r e l i a b l e Προσθέσαµε µια επιπλέον παράµετρο transm_model=stats_chain, που συλλέγει πληροφορίες για το σύνολο των µηνυµάτων που στέλνονται Το task chain_transm_model προσθέτει το µοντέλο reliable που τελικά µεταδίδει τα µηνύµατα Message -> stats_chain -> reliable Collecting Statistics Tasks Example 1. Φτίαχνουµε ένα αρχείο msgstats.conf στον ϕάκελο shawn/buildfiles και γράφουµε τις παρακάτω εντολές: Για να πάρουµε τα στατιστικά που συλλέγει το stats_chain µοντέλο χρησιµοποιούµε την εντολή: dump_transmission_stats : Τυπώνει τον συνολικό αριθµό µηνυµάτων που στάλθηκαν, καθώς και αναλυτικά τον αριθµό των διαφορετικών τύπων µηνυµάτων connectivity : Τυπώνει τον µέσο αριθµό γειτόνων των κόµβων καθώς και τον µέγιστο και ελάχιστο αριθµό γειτόνων prepare_world edge_model= l i s t comm_model= disk_ graph \ transm_model= s t a t s _ c h a i n range=1 chain_transm_model name= r e l i a b l e r e c t _ w o r l d width =50 height =50 count =5000 p r o c e s s o r s = h e l l o w o r l d c o n n e c t i v i t y d u m p _ t r a n s m i s s i o n _ s t a t s 2. Ανοίγουµε µια κονσόλα στον ϕάκελο shawn/buildfiles 3. Εκτελούµε την εντολή:./shawn -f msgstats.conf
Επισκόπηση Examples Πώς ϕτιάχνουµε µια νέα διεργασία στο shawn Πώς εισάγουµε ένα template processor στο shawn The Processor The Messages Πώς εισάγουµε ένα template application στο shawn Προετοιµασία της δοµής των ϕακέλων Ο κώδικας για τις διεργασίες(processors) που κατασκευάζουµε ϑα τοποθετούνται στον ϕάκελο src/legacyapps/ Αν δεν υπάρχει πρέπει να τον κατασκευάσουµε Κατεβάζουµε το ϕάκελο του legacyapps που περιέχει όλα τα απαραίτητα αρχεία: f t p : / / c a r r o t. c t i. gr /DS I / legacyapps. t a r. bz2 Αποσυµπιέζουµε το αρχείο στον ϕάκελο στην ϑέση shawn/src/: t a r x v j f legacyapps. t a r. bz2 ίνουµε την εντολή ccmake../src στον ϕάκελο shawn/buildfiles και µετά: Στην επιλογή LEGACYAPPS_PATH προσθέστε το ϕάκελο /home/<username>/shawn/src/legacyapps c, για να ενηµερωθεί για τις αλλαγές Ενεργοποιήστε την επιλογή CONFIGURE_LEGACYAPPS (πατώντας enter) c, για να ενηµερωθεί για τις αλλαγές g, για να αποθηκεύσει τις αλλαγές Τα αρχεία µιας διεργασίας Κατεβάζουµε το ϕάκελο που περιέχει όλα τα απαραίτητα αρχεία για την υλοποιήση ενός ένα κατανεµηµένου αλγόριθµου π.χ. : f t p : / / c a r r o t. c t i. gr /DS I /SHAWN Flooding Template. t a r. bz2 Αντιγράφουµε τον ϕάκελο στην ϑέση shawn/src/legacyapps/ Από την κονσόλα πηγαίνουµε στον ϕάκελο shawn/buildfiles ίνουµε την εντολή ccmake../src και µετά: c, για να ενηµερωθεί για τον νέο κώδικα που προσθέσατε Παρατηρούµε πως έχει εµφανιστεί µια νέα επιλογή στην πρώτη ϑέση µε το όνοµα της εφαρµογής (MODULE_LEGACYAPPS_FLOODING) Ενεργοποιήστε την επιλογή (πατώντας enter) c, για να ενηµερωθεί για τις αλλαγές g, για να αποθηκεύσει τις αλλαγές Τέλος δώστε την εντολή make για να γίνει compile το shawn Την παραπάνω διαδικασία την εκτελούµε µόνο όταν προσθέτουµε ένα νέο processor στον ϕάκελο legacyapps module.cmake : Περιέχει το όνοµα της νέας εφαρµογής που ενεργοποιούµε µε το ccmake simple_app_message.{cpp/h}: Περιέχει τα µηνύµατα που στέλνει ο αλγόριθµος simple_app_processor.{cpp/h}: Περιέχει τον κώδικα και τις µεταβλητές του αλγορίθµου, εδώ υλοποιούµε όλη την λογική της διεργασίας µας simple_app_processor_factory.{cpp/h}: Παρέχει 2 σηµαντικές συναρτήσεις, την create() και name(), που ϕτιάχνει ένα νέο processor και επιστρέφει το όνοµά του
The Processors Συναρτήσεις που µπορείτε να υλοποιήσετε (1 of 2) Μας επιτρέπουν να υλοποιούµε την λογική των κατανεµηµένων αλγορίθµων µας Μπορούµε να έχουµε πολλούς processors(διεργασίες) σε ένα κόµβο Αλγόριθµο Tree Routing Αλγόριθµο Leader election Εχουν τρεις καταστάσεις Active: Πλήρη λειτουργία Sleep: εν δέχονται µηνύµατα Inactive: Καµία λειτουργία Αν όλοι οι processors σε ένα κόµβο είναι Inactive τότε ο κόµβος γίνεται Inactive Αν όλοι οι κόµβοι είναι Inactive η εξοµοίωση τερµατίζει Ακολουθεί µια λίστα µε ϐασικές συναρτήσεις που µπορείτε να υλοποιήσετε µέσα στον processor void boot() Εκτελείται µια ϕορά για κάθε processors στην αρχή της εξοµοίωσης.χρησιµοποιείται συνήθως για αρχικοποίηση του αλγορίθµου µας. void special_boot() Εκτελείται µια ϕορά για κάθε processors που ϐρίσκεται σε ένα ειδικό (special) κόµβο. Καλείται πριν την boot() void work() Εκτελείται µια ϕορά για κάθε γύρο (iteration) της εξοµοίωσης. Χρησιµοποιείται για την εκτέλεση περιοδικών tasks. Συναρτήσεις που µπορείτε να υλοποιήσετε (2 of 2) Χρήσιµες συναρτήσεις που µπορείτε να καλέσετε bool process_message(messagehandle& ) Εκτελείται όταν ο κόµβος λάβει ένα µήνυµα. Το µήνυµα παραδίδεται στους processors του κόµβου. Μπορεί να λάβει διαφορετικά µηνύµατα οπότε πρέπει να εξετάζουµε τον τύπο του µηνύµατος. bool MyProcessor : : process_message ( const shawn : : ConstMessageHandle& mh ) { const MyMessage mymsg = dynamic_cast < const MyMessage > ( mh. get ( ) ) ; i f ( MyMessage! = NULL ) { / / handle my message r e t u r n t r u e ; } r e t u r n shawn : : P r o c e s s o r : : process_message ( mh ) ; } Ακολουθεί µια λίστα µε ϐασικές συναρτήσεις που µπορείτε να καλέσετε µέσα στον processor void send(messagehandle& ) Στέλνει ένα µήνυµα στους γείτονες π.χ. : send ( new FloodingMessage ( ) ) ; void set_state() Θέτει την κατάσταση του processor π.χ. : s e t _ s t a t e ( Sleep ) s e t _ s t a t e ( I n a c t i v e ) int simulation_round() Επιστρέφει τον γύρο στον οποίο ϐρίσκεται η εξοµοίωση int id() Επιστρέφει το id του κόµβου
Τα µηνύµατα στο Shawn Ολα να µηνύµατα που στέλνουµε είναι κλάσεις και ϐρίσκονται συνήθως στα αρχεία <name>_message.{h/cpp}. Και κληρονοµούν από την κλάση shawn Message c l a s s MyMessage : p u b l i c shawn : : Message { p u b l i c : MyMessage ( ) ; v i r t u a l MyMessage ( ) ; } ; Κάθε πρωτόκολλο υλοποιεί τα δικά του µηνύµατα, δηλαδή διαφορετικές κλάσεις Κάθε processor κάνει cast το γενικό µήνυµα που λαµβάνει στην process_message(messagehandle& ) για να πάρει το δικό του µήνυµα const FloodingMessage mymsg = dynamic_cast < const FloodingMessage > ( mh. get ( ) ) ; Τα µηνύµατα στο Shawn Το παρακάτω µήνυµα έχει µια µεταβλητή id_ και µια συνάρτηση id() για να την διαβάζουµε Αποστολή ενός µηνύµατος : send( new FloodingMessage(3) ) Παράδειγµα κώδικα ενός µηνύµατος (flooding_message.h) c l a s s FloodingMessage : p u b l i c shawn : : Message { p u b l i c : FloodingMessage ( i n t ) ; v i r t u a l FloodingMessage ( ) ; i n l i n e i n t i d ( void ) const throw ( ) { r e t u r n i d _ ; } ; p r i v a t e : i n t i d _ ; } ; Τα µηνύµατα στο Shawn - Παράδειγµα Χρήσιµες διευθύνσεις Προσθέστε τις δυο παρακάτω γραµµές κώδικα στις αντίστοιχες συναρτήσεις void boot ( void ) {... send ( new FloodingMessage ( ) ) ;... } void handle_flooding_message ( const... ) {... cout << " Elaba ena neo Flooding message " << endl ;... } Κάνουµε compile το shawn εκτελώντας στον ϕάλεκο shawn/buildfiles την εντολή make Εκτελούµε το shawn χρησιµοποιώντας το hello.conf αλλάζοντας τον processor σε flooding Οδηγίες εγκατάστασης του shawn (για windows Visual Studio, Linux, MAC): h t t p : / / shawn. s f. net Ubuntu shawn image: f t p : / / c a r r o t. c t i. gr /DS I / ubuntu_shawn_image. 7 z