EÖTVÖS LORÁND TUDOMÁNYEGYETEM TERMÉSZETTUDOMÁNYI KAR INFORMATIKAI TANSZÉKCSOPORT
Mini Multi Agent System 2003 június
Készítette: Terray Tamás Témavezető: Gulyás László
Tartalom TARTALOM......................................................................................................................................................................2 BEVEZETÉS......................................................................................................................................................................4 A RENDSZER CÉLJA.............................................................................................................................................................4 A RENDSZER FELÉPÍTÉSE......................................................................................................................................................4 A FEJLESZTÉS TANULSÁGAI....................................................................................................................................................4 A TOVÁBBFEJLESZTÉS IRÁNYA................................................................................................................................................5 FELHASZNÁLÓI DOKUMENTÁCIÓ...........................................................................................................................6 DEFINÍCIÓK.........................................................................................................................................................................6 SZÜKSÉGES FUTÁSI KÖRNYEZET..............................................................................................................................................6 TELEPÍTÉS..........................................................................................................................................................................6 KONFIGURÁLÁS...................................................................................................................................................................6 ÁGENS TÉNYHALMAZÁNAK ÉS CSELEKVÉSEINEK BEÁLLÍTÁSA.......................................................................................................7 ÚJ TÉNYEK, KÖVETKEZTETÉSEK FELVÉTELE..............................................................................................................................7 ÚJ CSELEKVÉSEK FELVÉTELE..................................................................................................................................................7 Cselekvés fejlesztése...................................................................................................................................................7 A cselekvés tulajdonságainak rögzítése.....................................................................................................................8 FUTTATÁS...........................................................................................................................................................................8 PÉLDA FUTTATÁSOKRA: ........................................................................................................................................................8 Sima számlálás ..........................................................................................................................................................8 Számlálás + idő lekérése ágenstől ............................................................................................................................8 Számlálás + ágenslista lekérése ...............................................................................................................................9 Számlálás + időlekérés + automatikus ágenslista frissítés ......................................................................................9 Számlálás + időlekérés + levélküldés .......................................................................................................................9 Számlálás + szerver teszt...........................................................................................................................................9 FEJLESZTŐI DOKUMENTÁCIÓ................................................................................................................................10 AZ ÁGENS FELÉPÍTÉSE.........................................................................................................................................................10 Az ágens életciklusa.................................................................................................................................................10 Tények, Szabályok....................................................................................................................................................10 Cselekedetek.............................................................................................................................................................10 Az ágenst futtató környezet......................................................................................................................................11 ÁGENSEK KÖZÖS MŰKÖDÉSE................................................................................................................................................11 Az ágenslista............................................................................................................................................................11 Kommunikáció.........................................................................................................................................................11 KÖNYVTÁRAK ÉS FILEOK:....................................................................................................................................................11 Főkönyvtár:..............................................................................................................................................................11 lib.............................................................................................................................................................................12 log............................................................................................................................................................................12 pid............................................................................................................................................................................12 dat............................................................................................................................................................................12 doc............................................................................................................................................................................12 example....................................................................................................................................................................12 modul_test................................................................................................................................................................13 agent_2.....................................................................................................................................................................13 tmp............................................................................................................................................................................13 FORRÁSKÓD RÉSZLETEI.......................................................................................................................................................14 Mmas.pl....................................................................................................................................................................14 Config.pl...................................................................................................................................................................15 Action.pl...................................................................................................................................................................16 Server.pl...................................................................................................................................................................25 communicator_misc.pl.............................................................................................................................................27
2
xml_misc.pl..............................................................................................................................................................33 TO-DO LISTA....................................................................................................................................................................35 FUTTATÁS KIMENETE...............................................................................................................................................36
3
Bevezetés
A Rendszer célja A fejlesztés célja hogy megvalósítson egy olyan multi-ágens rendszert (amely több, önállósággal rendelkező, és egymásra ható entitás összessége), melyben a szereplő ágensek rendelkeznek az önálló következtetés és az együttműködés lehetőségével. A megvalósítandó rendszer tehát tudásalapú, cselekvésekre képes entitások hálózata. A rendszer alapötlete a hálózatokat diagnosztizáló megosztott rendszerekből ered. A modern hálózatdiagnosztikai rendszerek már rendelkeznek a megosztottság tulajdonságával, bennük magasabb terhelhetőség és bizonyos fokú munkamegosztás válik lehetővé. Ehhez képest előrelépést az ilyen diagnosztikai hálózatba rendezett ágensek esetén a különálló entitások ’okosabbá tétele’ és a feladatkisztás rugalmasabbá tétele jelentheti. Az okosabbá tétel megvalósítását tudásalapú ágensek használatával célozzuk meg, míg a feladatkiosztás rugalmasabbá tételét azzal, hogy az ágensek forráskódja azonos kell hogy legyen, pillanatnyi szerepük ne felépítésüktől, hanem helyzetüktől függjön. A rendszerrel kapcsolatos elvárás hogy egyszerre tartalmazzon valamelyest önálló entitásokat, és azok tudjanak egymással kommunikálni. A cél annak vizsgálata volt hogy ágensek ilyen hálózata a hibatűrés magasabb fokát valósítja-e meg. További elvárás volt, hogy a rendszer ‘demokratikus’ megosztottsága erősítse a rendszer rugalmasságát. Gyakorlati megkötés, hogy az ágensek egy vagy több hoszton is futhassanak, futtatásuk és kommunikációjuk elterjedt eszközökre épüljön. A kitűzött cél nem egy gyakorlati alkalmazás létrehozása, hanem egy olyan keretrendszer építése, mely alkalmas a továbbfejlesztésre, és a gyakorlatban teszteli az alapötlet életképességét.
A Rendszer felépítése A rendszer több, egymástól független, de egymással kapcsolatban lévő, önnálló ágens összessége. Az ágensek folytonosan, akár háttérben is futhatnak hosztjaikon (akár démonként is). Futásuk során egy tényhalmazt tartanak karban maguknak, mely a kezdeti tények, a többi ágenstől elnyert információkból cselekvéseik, és következtetéseik alapján áll elő. Az ágensek ezen tényhalmaz és következtetési szabályaik alapján működnek. Futásuk során a tényhalmazuk alapján választják ki az aktuálisan végrehajtandó cselekvéseket, melyek természetesen változtatják a tényhalmazt. A változó tényhalmazból a következtető rendszerük próbál új következtetések levonásával egy teljesebb tényhalmazt kialakítani. Az ágens akkor áll le, amikor tényhalmazába bekerül a leállására felszólító tény. Az ágensek hálózatára a rugalmas központosítás jellemző. Az ágensek forráskódja alapértelmezett helyzetben nem tér el egymástól, viszont egy prioritás tulajdonságon keresztül rendezve vannak
A fejlesztés tanulságai A fejlesztés során sikerült a kitűzött célként meghatározott rendszert előállítani. A megvalósított ágensek összessége olyan hálózatot alkot, mely rugalmasan képes viselkedni, a környezettől kapott 4
tények felhasználásával. A mostani rendszer működő keretet nyújt olyan fejlesztésekhez, melyekben gyakorlati problémákat oldunk meg multiágens rendszerrel. A továbbfejlesztés iránya így az ágensek által felhasználható cselekvések körének bővítése.
A továbbfejlesztés iránya Mivel a modellrendszer működik, azon érdemes elgondolkodni hogy a továbbfejlesztések és a gyakorlati hasznosítás milyen problémákat vethetnek fel, és azokra milyen válasz adható a fejlesztések tervezése során. Ilyen kérdés lehet a következtetőrendszerekkel kapcsolatos nagy mennyiségű tény kezelésével kapcsolatos probléma, vagy a teljes rendszer tényhalmazának a nehézkes megjelenítése a felhasználó felé. A rendszer hatékonyságát növelő gyakorlati tennivalókra vonatkozó ötletek a To-Do listában megtalálhatóak.
5
Felhasználói dokumentáció Definíciók • • • •
Ágens: Nincs általánosan elfogadott definíciója, ebben a dokumentációban a rendszer olyan részeire értjük, melyek képesek valamilyen szintű önállóságra. Multi Ágens rendszer: Több ágens együttes rendszere, melyben az ágensek hatással vannak egymásra. Főnök: A jelen programrendszerben a legmagasabb prioritású ágens hivatkozása. Démon: Jelen dokumentációban olyan processzekre hivatkozunk így, melyek háttérben futnak hosztjukon, nem használják a standard ki és bemeneteket meneteket (stdout, stderr, stdin).
Szükséges futási környezet A program futtatásához csak standard 5.0-ás vagy annál újabb Perl-re van szükség, az egyéb felhasznált csomagok a rendszer részét képezik. A rendszer a perl-t annak Un*x és Linux rendszerekben szokásos helyén a /usr/bin/perl helyen keresi
Telepítés A tgz file kicsomagolása után a fent leírt környezetekben nem szükséges más beállítást eszközölni.
Konfigurálás A konfigurálás a rendszer főkönyvtárában lévő config.pl állomány szerkesztésével történik. A konfigurálható értékek, és alapértelmezéseik: • • • • • • • • • •
'daemon_mode' => 0, # démonként fusson e az ágens 'max_conn' => 10, # maximálisan ennyi ágens kapcsolódhat egyszerre ehhez az ágenshez 'dir' => '.', # démon chroot dir 'pidfile' => 'pid/ts.pid', # pidfile / under $sonfig{'dir'} 'logfile' => 'log/ts.log', # logfile / under $config{'dir'} 'errorlogfile' => 'log/tserr.log', # errorlog / a $config{'dir'} alatt 'agentfile' => 'dat/agent.list', # ágens lista file a $config{'dir'} alatt 'xml_ver' => '0.1', # ágens által használt xml struktúra verziószáma 'agent_ver' => '0.7', # ágens verziószáma 'loglevel' => 1, # logolás szintje. A szint alatt levő események logolódnak 6
• • • • •
'errorloglevel' error logolódnak 'debuglevel' jelennek meg. 'send_mail' helye 'send_mail_user' küldjük ’operator_mail'
=> 1,
# errorlog szintje.A szint alatt levő események
=> 10,
# debug szintje. A szint alatt levő események
=> '/usr/sbin/sendmail', # levélküldéshez használt külső program => 'neurotic'
# a felhasználó akinek a nevében a levelet
=>'neurotic'
# az operátor címe, aki felelős az ágensért
# ágens önmagárol szóló információi • 'id' => 'agent_1' # egyedi azonosító • 'peer_port' => '1999' # a használt port, redundáns, mert az ágenslistában is benne van, de már az ágens inicializálása előtt szükség van rá.
Ágens tényhalmazának és cselekvéseinek beállítása A rendszer aktuális futása az actions.pl file-ban kiválasztott kezdeti tényhalmaztól függ. A választható tényhalmazok mintákat mutatnak be arról hogy milyen tények és szabályok választhatóak melyek természetesen meghatározzák a rendszer lefutását. Így ennek a file-nak a tartalmát kell ahhoz változtatni hogy másképpen fusson le a rendszer, és a további fejlesztések legnagyobb része is arra irányul hogy az ebben lévő cselekvések köre kibővüljön. A kész tényhalmazok közül az init_rules eljárásban kell kiválasztani azokat, melyek indításkor betöltődnek az ágensbe. A tényhalmazok eljárásainak nevei f_r karakterekkel kezdődnek.
Új tények, következtetések felvétele Természetesen fel lehet venni új tényhalmazokat is, az új tények felvételénél egy dologra kell jelenleg figyelni: a felhasznált következtetőrendszer sajátossága hogy a következtetési szabályokat nem a hagyományos, hanem fordított sorrenddel jelöli. Tehát egy A => B alakú szabályt a rendszer ’B-ből következik A’-ként értelmez. A szabályok felvételével kapcsolatban érdemes az action.pl programban, és a modul_test könyvtárban található következtetési rendszer mintaprogramokban lévő példákat tanulmányozni.
Új cselekvések felvétele Cselekvés fejlesztése A cselekvések a felhasznált perl programozási nyelv eljárásai, melyekre igaz néhány megkötés. Cselekvések fejlesztésekor be kell tartani a nevükkel kapcsolatos konvenciót, tehát az action_ karakterlánccal kell bevezetni az eljárás nevét. Emellett a cselekvések visszatérési értékének egy hármasnak kell lennie az alábbi sorrendben: • Tényhalmazba kerülő új tények tömbjére mutató referencia • Tényhalmazból kiveendő tények tömbjére mutató referencia • Egyéb visszatérési értékek, melyek a cselekvések esetleges normál eljárásként való meghívásakor használható.
7
Ezen megkötések mellett az akciók belső felépítését nem szabályozza más szabály.
A cselekvés tulajdonságainak rögzítése A fejlesztett cselekvések akkor aktiválódnak csak, ha leírásuk bekerül a cselekvéseket tartalmazó adatstruktúrába, mely alapján a futtató eljárás kiválasztja az aktuálisan futtatandó cselekedeteket. Egy cselekvésről az alábbi adatokat kell rögzíteni: • prioritás • tüzelési feltételek listája • tüzelés-tiltási feltételek listája • valószínű tény és szabály bővítési lista • valószínű tény és szabály szűkítési lista
Futtatás Az ágensek indításához a szerver környezetet kell elindítanunk, melyet a kiválasztott ágens könyvtárában kiadott './server.pl start' parancsal tehetünk meg. A leállítás ugyanezen parancs stop paraméteres meghívásával, a status lekérése (fut e a rendszer) a status paraméter használatával történik. Ezkkel a parancsokkal az ágenst futtató szerver környezetet érjük el.
Példa futtatásokra: A példafuttatások kimenetei az example/outputs/ könyvtárban találhatóak. A kimenetek a rendszer korábbi verzióival is születhettek, nem feltétlenül egyeznek a jelenlegi rendszer kimeneteivel.
Sima számlálás Példafile: fr_tik_tak.txt Leírás: Ez a futtatás egy egyszerű számlálást hajt végre. Minden lépésben eggyel növeli az ágens egy számlálo értéket. Indítás módja: action.pl-ben az init_rules eljárásban az fr_tik_tak - on kívül mindent ki kell kommentezni. Ezek után elindítani az ágenst, majd leállitani.
Számlálás + idő lekérése ágenstől Példafile: fr_get_time__boss.txt, fr_get_time__notboss.txt Leirás: Ebben a cselekvéssorban az alacsonyabb prioritással rendelkező ágens lekerdézi a főnöktől az időt. Indítás módja: az action.pl-ben az init_agent eljárásban az f_r_tik_tak es f_r_get_time-on kívül a többit ki kell kommentezni. Ezek után két ágenst kell indítani: az alapot, a főkönyvtárban és az agent_2-t az alkönyvtárában. Leállitani csak a külsőt kell, a másik leáll magától.
8
Számlálás + ágenslista lekérése Példafile: fr_get_agent_list__nboss.txt, fr_get_agent_list__boss.txt Leírás: Ebben a cselekvési sorban az alacsonyabb prioritású ágenst felszólítjuk hogy frissítse ágenslistáját, amit a főnöktől kér le ezek után. Ezt az akciot az ágens automatikusan is végrehajthatja, ha egy magasabb prioritású ágenssel kommunikálva észreveszi, hogy annak magasabb verziószámu ágenslistája van. Indítás módja: az action.pl-ben az init_agent eljárásban az f_r_tik_tak és f_r_get_agent_list-en kívül a többit ki kell kommentezni. Ezek után két ágenst kell indítani: az alapot, a főkönyvtárban és az agent_2-t az alkönyvtárában. Leállítani csak a külsőt kell, a másik leáll magától.
Számlálás + időlekérés + automatikus ágenslista frissítés Példafile: fr_get_time___get_agent_list__nboss.txt Leirás: Ebben a cselekvéssorban az alacsonyabb prioritással rendelkező ágens lekérdezi a főnöktől az időt. Emellett ha alacsonyabb prioritású ágensnek kissebb az ágenslista verziója, akkor automatikusan lekéri az ágenslistát is. Indítás módja: Elsőként ha egyeznek az ágenslista verziószámok (a dat könyvtárban található agent.list XML-file ban találhatóak), akkor a magasabb prioritásúnak növelni kell az ágenslista verziószámát. Ezek utan a 2. példának megfelelően kell indítani az ágenseket.
Számlálás + időlekérés + levélküldés Példafile: fr_get_time___send_mail__nboss.txt Leírás: Ebben az esetben az előzőhöz hasonló módon egy automatizmus indul el. Az alacsonyabb prioritású ágens észreveszi hogy újabb verzió is van már az ágensekből, és erről emailben értesíti az operátort. Indítás módja: 2,4-nek megfelelő indítás mellett gondoskodni kell róla, hogy az ágensek konfigurációs file-jában megadott agent_ver verziószám eltérjen egymástól, a főnök javára.
Számlálás + szerver teszt Példafile: f_r_server_test.txt Leírás: Ebben az esetben egy mini minta alkalmazást indítunk el. Az eljárás végigellenőrzi egy konfigurációs állományban leírt szervereken futó szolgáltatásokat, és az eredményeket log file-ban rögzíti. Emellett bizonyos hibák esetén értesíti az adott rendszer gazdáját. Indítás módja: Indításkor az f_r_server_test eljárás meghívásra kell kerüljön.
9
Fejlesztői dokumentáció Az ágens felépítése Az ágens életciklusa A megvalósított ágensek szabály alapúak. Működésük kezdetén beolvassák az aktuálisan igaz tényeket, szabályokat, és a végrehajtható cselekedeteket, és azok határozzák meg késöbbi működésüket. Az ágens önmaga inicalizálás után egy ciklusba kezd, mely akkor ér véget ha kikövetkezteti saját leállítását. Ebben a főciklusban: • Ellátja a kommunikációs feladatokat • Kiválasztja az aktuálisan végrehajtható cselekvéseket (az aktuális tények alapján) • A cselekvések visszatérési értékével megváltoztatja az aktuális tényhalmazt • Lefuttatja a következtető eljárását, mely igyekszik minél több ténnyel bővíteni a tényhalmazt. A cselekedetek végrehajtását a kiválasztott futtató eljárás végzi el. Jelenleg csak egyetlen, nagyon egyszerű futtató metódus van, mely minden végrehajtható cselekvést elindít. Ez az eljárás a cselekvések prioritását sem veszi figyelembe, ami pedig javíthatná az ágensek hatásfokát (így ez szerepel is a tennivalók listájában).
Tények, Szabályok Ezek az információk az action.pl fileban találhatóak. Az átláthatóság kedvéért eljárásokba vannak gyűjtve olyan tények és szabályok melyeknek a tényhalmazba töltése bizonyos működést vált ki az ágensből. Ezeket az eljárásoknak a neve a jelenlegi elnevezési konvenció szerint f_r_ - el kezdődik és nevük a kiváltott cselekvéssorra utal.
Cselekedetek A rendszer által végrehajtható cselekedetek is az action.pl file-ban vannak eltárolva. A cselekedetek elnevezése a jelenlegi konvenció szerint action_ karakterlánccal kezdődik. Ezekhez a cselekedetekhez tartozik egy adatszerkezet melyben a cselekedeteknek a tényekhez való kapcsolatai vannak leírva. Ezen információk alapján tudja a futtató eljárás eldönteni hogy mely cselekedetet hajtsa végre. A cselekedeteket jellemző adatok: • prioritás • tüzelési feltételek listája • tüzelés-tiltási feltételek listája • valószínű tény és szabály bővítési lista • valószínű tény és szabály szűkítési lista A cselekedetek visszatérési értékei: • bővítési lista • törlési lista • visszatérési értékek 10
Az ágenst futtató környezet A felhasználó nem közvetlenül az ágenseket indítja el, hanem egy szerver környezetet, amely biztosítja az ágens környezetét. A szerver környezet funkciói • Port foglalása • Nem blokkolt módú kommunikáció megvalósítása • Futás háttérben, démonként
Ágensek közös működése Az ágenslista Az ágensek folyamatosan karbantartanak egy listát amiben az általuk ismert többi ágens adatai találhatóak. A lista alapján egyértelműen eldönthető hogy az adott pillanatban melyik ágensnek a legmagasabb a prioritása, ezt az ágenset nevezzük röviden főnöknek. Az ágenslista karbantartása operátori oldalról igen egyszerű, a főnök ágensnek kell csak az ágenslistáját változtatni, ezek után az új információk elterjednek a hálózatban. Az ágenslista frissítését explicit módon is lehet kérni, illetve kommunikácó során az ágensek is vizsgálják annak naprakészségét. Az ágenslista fizikailag egy file-ban, XML formátumban tárolódik , a file helyét a konfigurációs álloömányban lehet megadni (alapbeállítás: dat/agent.list). Az XML file-ban egy ágenslista verziószám is helyet kap, ennek segítségével lehet gyorsan összehasonlítani két ágens listáját. Az ágenslista frissítésére is található példa a felhasználói dokumentációban.
Kommunikáció Bizonyos cselekedetek végrehajtásakor az ágensek kommunikálnak is egymással, ez Tcp/Ip socket felett nem blokkolt módon van megvalósítva. A kommunikácó XML kérések és válaszok segítségével történik. Ennek oka, hogy a fejlesztések során rugalmasan lehet változtatni az átküldött információkat, az XML rugalmasságának köszönhetően a régebbi verziójú ágensek számára is fennt lehet tartani a régi információkat.
Könyvtárak és fileok: Az alábbiakban a rendszer fontosabb file-jainak ismertetése található. A részletes információ a file-okban található megjegyzésekben van.
Főkönyvtár: • • •
actions.pl : a végrehajtható cselekvések gyűjteménye config.pl : konfigurációs állomány mmas.pl : főprogram 11
•
server.pl : szerver környezetet megvalósító állomány
lib Felhasznált saját és külső modulok könyvtára • • • • •
•
communicator_misc.pl : kommunikációs eljárások my_Proplog.pm : Következtetési eljárások propose_misc.pl : Következtetési kiegészítés server_misc.pl : Szerver eljárások Writer.pm : XML Writer modul xml_misc.pl : XML kiegészítő eljárások
log rendszer log könyvtár • •
tserr.log : error log ts.log : normál log
pid rendszer process id-t tartalmazó file helye • ts.pid: rendszer process id-t tartalmazó file
dat Adatkönyvtár • agent.list : ismert ágensek listája
doc Dokumentáció könyvtár • README.TXT : Ennek a leírásnak az első verziója • Dokumentacio.doc: Ez a leírás • todo.txt : tennivalók a fejlesztésben
example Példák a rendszer futtatására ./example/outputs: rendszer futásának kimenetei Részletes leírásuk a Példafuttatásoknál
12
modul_test A felhasznált modulok tesztelésére szolgált programok helye
agent_2 másolat a rendszerről, párhuzamos futtatáshoz • config.pl : saját konfigurációkat tartalmazza
tmp Ebben a könyvtárban hozhatják létre az eljárások saját temporálos file-jaikat. Azért nem használhatják a közös tmp könyvtárat, mert démonként futtatva a rendszer chroot környezezetben működik (nem ér el külső könyvrárakat).
13
Forráskód részletei Mmas.pl #!/usr/bin/perl ################################################################################ # Ez a file tartalmazza az agens foprogramjat. ################################################################################ # az agenst megvalosito eljaras sub mmas { # az agenshez beerkezett informaciokereseket tartalmazo hash %query = (); # kovetkeztetogep inicializasa init_propose(); # aktualis tenyhalmaz betoltese init_rules(); # ismert akciok betoltese load_actions(); log_err_deb(Dumper($p->{clause}), 0, 0, 3); # az agens fo ciklusa while(! $p->is_true('stop_agent')) { # kovetkeztetes $p->propose(); # akciok vegrehajtasa runner(); # kommunikacio ellatasa communicate(); log_err_deb('Tenyhalmaz ' . Dumper($p->{established}), 0, 0, 1); };
};
# az akciok futtatasanak eljarasa sub runner { # a futtato/utemezo kivalasztasa, mely eldonti hogy mely akcio[k] hajtodjon [hajtodjanak] vegre dummy_runner(); }; # ez a legegyszerubb (es egyenlore egyetlen) futtato sub dummy_runner { # mindent akciot lefuttat amit lehet, es nem is rendezi sorba oket. foreach $action (keys(%actions)) { # minden akciora megvizsgalja hogy teljesulnek e a feltetelei # es ha igen, akkor lefuttatja. if($p->is_true($action)) { log_err_deb("Inditas $action ($actions{$action}{'comment'})", 0, 0, 5);
14
$evalstr = '($bovites, $torles, $vals)' . " = action_$action()"; # az akcio futtatasa, a neki megfelelo fuggveny kiertekelese a jelenlegi kontextusban eval($evalstr); log_err_deb("Visszateres @{$bovites} :: @{$torles} :: @{$vals}", 0, 0, 5); # a visszateresi ertekek atvezetese a tenyhalmazba $p->update_facts($bovites, $torles); }; }; };
Config.pl #!/usr/bin/perl ################################################################################ # Konfiguracios file ################################################################################ # altalanos beallitasok %config = ( 'daemon_mode' => 0, 'max_conn' => 10, kapcsolodhat egyszerre 'dir' => '.', 'pidfile' => 'pid/ts.pid', {'dir'} 'logfile' => 'log/ts.log', {'dir'} 'errorlogfile' => 'log/tserr.log', {'dir'} 'agentfile' => 'dat/agent.list', $config{'dir'} 'xml_ver' => '0.1', verzioszama 'agent_ver' => '0.7', 'loglevel' => 1, alatt levo esemenyek logolodnak 'errorloglevel' => 1, alatt levo esemenyek error logolodnak 'debuglevel' => 10, alatt levo esemenyek jelennek meg. 'sleep' => { eltelheto idok 'min' => 1, 'mid' => 10, 'max' => 60 }, 'send_mail' => '/usr/sbin/sendmail', kulso program helye 'send_mail_user' => 'neurotic', neveben a levelet kuldjuk 'operator_mail' => 'neurotic' felelos az agensert
# maximalisan ennyi agens # daemon chroot dir # pidfile / under $sonfig # logfile
/ under $config
# errorlog / under $config # agens lista file / under # agens altal hasznalt xml # agens verzioszama # logolas szintje. A szint # errorlog szintje.A szint # debug szintje. A szint # ket csekekves kozott
# levelkuldeshez hasznalt # a felhasznalo akinek a # az operator cime, aki
15
); # agens magarol szolo informacioi $config{'self'} = { 'id' => 'agent_1', # egyedi azonosito 'peer_port'=> '1999' # hasznalt port, redundans, mert az agenslistaban is benne van, de mar az agens inicializalasa elott szukseg van ra. }
Action.pl #!/usr/bin/perl ################################################################################ # Ez a file tartalmazza: # - a vegrehajthato cselekveseket # - tenyhalmazgyujtemenyeket # - aktualis tenyhalmaz valasztast # a kivalasztott cselekves fugg az aktualis tenyhalmaztol ################################################################################ ################################################################################ # A lenyeg: kivalasztjuk hogy az agens milyen tenyhalmazzal induljon ################################################################################ # itt inditjuk el az agensben az altalunk valasztott cselekveseket sub init_rules { # f_r_0; f_r_tik_tak(); # f_r_send_mail(); # f_r_get_time(); # f_r_get_agent_list(); f_r_server_test(); }; ################################################################################ # cselekvesek melyeket az agens vegrehajthat ################################################################################ # # # # # # # # # # # # # #
a cselekveseket (akciokat) tartalmazo hash ertekei a vegrehajthato cselekvesek, azok tulajdonsagai: - prioritas - tuzelesi feltetelek listaja - tuzeles-tiltasi feltetelek listaja - valoszinu teny es szabaly bovitesi lista - valoszinu teny es szabaly szukitesi lista a cselekvesek fuggvenyek melyek visszateresi erteke egy 3-as lista: - bovitesi lista - torlesi lista - visszateresi ertekek
16
%actions = ( 'sleepr' => { 'pri' => 0, 'cond' => 'sleep_min sleep_mid sleep_max', 'n-cond' => 'sleep_null', 'fact-plus' => '', 'fact-minus' => '', 'comment' => 'Pihenteti az agenst egy idore' }, 'tik_tak' => { 'pri' => 0, 'cond' => 'tik_tak', 'n-cond' => '', 'fact-plus' => '', 'fact-minus' => '', 'comment' => 'Novel egy szamlalot' }, 'init_agent' => { 'pri' => 0, 'cond' => 'init_agent', 'n-cond' => '', 'fact-plus' => '', 'fact-minus' => 'init_agent', 'comment' => 'Inicializalja az agenst.' }, 'get_time' => { 'pri' => 0, 'cond' => 'get_time', 'n-cond' => '', 'fact-plus' => '', 'fact-minus' => '', 'comment' => 'Lekeri az idot a legmagasabb prioritasutol' }, 'send_time' => { 'pri' => 0, 'cond' => 'query_get_time', 'n-cond' => '', 'fact-plus' => '', 'fact-minus' => 'query_get_time', 'comment' => 'Megvalaszolja a pontos idot' }, 'get_agent_list' => { 'pri' => 0, 'cond' => 'get_agent_list', 'n-cond' => '', 'fact-plus' => '', 'fact-minus' => '', 'comment' => 'Lekeri az agens listat a legmagasabb prioritasutol' }, 'send_agent_list' => { 'pri' => 0, 'cond' => 'query_get_agent_list', 'n-cond' => '', 'fact-plus' => '', 'fact-minus' => 'query_get_agent_list', 'comment' => 'Elkuldi az agensek listajat egy kliensnek'
17
}, 'send_mail' => { 'pri' 'cond' 'n-cond' 'fact-plus' 'fact-minus' 'comment' }, 'server_test' => 'pri' 'cond' 'n-cond' 'fact-plus' 'fact-minus' 'comment' szervereken' }
=> => => => => =>
0, 'send_mail(v_1)(v_2)(v_3)(v_4)', '', '', 'send_mail(v_1)(v_2)(v_3)(v_4)', 'Elkuld egy levelet'
{ => => => => => =>
0, 'server_test', '', '', 'server_test', 'Letesztel konfig fileban leirt szolgaltatasokat
); # a legegyszerubb cselekves egy agens szamara is : alvas sub action_sleepr { # a tenyhalmazban levo alvasmennyiseget valasztjuk if($p->is_true('sleep_max')) { sleep($config{'sleep'}{'max'}); } elsif ($p->is_true('sleep_mid')) { sleep($config{'sleep'}{'mid'}); } elsif ($p->is_true('sleep_min')) { sleep($config{'sleep'}{'min'}); }; return ([], [], []); }; # egy szamlalot megvalosito cselekves. Lepesenkent eggyel noveli a szamlalo erteket. sub action_tik_tak { my ($tik_tak) = $p->get_f_val('tik_tak'); return (["'tik_tak(" . ($tik_tak + 1) . ")'"], ["tik_tak($tik_tak)"], []); }; # egy levelkuldest megvalosito akcio sub action_send_mail { my ($from, $to, $subject, $message) = $p->get_f_val('send_mail'); send_mail($from, $to, $subject, $message); return ([], ["send_mail($from)($to)($subject)($message)"], []); }; # idolekerest megvalosito cselekves. A legmagasabb prioritasu agenstol keri le az idejet. sub action_get_time { my ($boss_id) = $p->get_f_val('boss'); my $hashref = q_agent($boss_id, "get_time"); my $time = ${$hashref}{'reply'}{'answer'}{'astr'}; return (["'time_got(" . $time . ")'"], ["get_time"], []); };
18
# idolekeresre valaszolo cselekves. A legmagasabb prioritasu agens hajtja vegre. sub action_send_time { $query{'query_get_time'}{'answer'} = $p->get_f_val('tik_tak'); return ([], ["query_get_time"], []); }; # agenslista lekerese a legmagasabb prioritasu agenstol. sub action_get_agent_list { my ($boss_id) = $p->get_f_val('boss'); my @fact = (); my $hashref = q_agent($boss_id, "get_agent_list"); %agent_list = %{${$hashref}{'reply'}{'answer'}{'astr'}}; if(%agents == %agant_list) { log_err_deb("Nincs szukseg az agenslista aktualizalasara", 0, 0, 3); } else { log_err_deb("Agenslista aktualizalasa, uj adat: " . Dumper(\%agent_list), 0, 0, 3); # agenslistat tartalmazo file megnyitasa felulirasra my $output = new IO::File(">" . $config{'agentfile'}); # uj adatok kiirasa a fileba write_hash_2_xml(\%agent_list, \$output); # file zarasa close($output); # boviteni kell a tenyhalmazt az ujrainicializalas szuksegessegevel push(@fact, "'init_agent'");
}; push(@fact, "'agent_list_got'"); return (\@fact, ["get_agent_list"], []);
};
# agenslista kuldese alacsonyabb prioritasu agensnek. sub action_send_agent_list { $query{'query_get_agent_list'}{'answer'} = $agent_file; return ([], ["query_get_agent_list"], []); }; # az agens inicializalasa # cselekedetei: # agenslista beolvasasa # fonok agens kivalasztasa (legmagasabb prioritasu) sub action_init_agent { # agenslista uresse tetele %agents = (); # agens adatokat tartalmazo file tartalmanak uritese $agent_file = ''; my @fact; # agenslista file megnyitasa open(AF, $config{'agentfile'}) or log_err_deb("Can not open agent data file " . $config{'agentfile'}, 0, 1, 1); # az XML formatumu agenslista file beolvasasa while(
) { chomp($_);
19
$agent_file .= $_; }; # agensfile lezarasa close(AF); # parser inicalizalasa $parser = new XML::Parser( Style => 'Tree' ) or log_err_deb("XML parser inicializalas sikertelen az agens file olvasasahoz", 0, 1, 1); my $tree = $parser->parse($agent_file) or log_err_deb("XML agens file feldolgozasa sikertelen", 0, 1, 1); # megprobaljuk hash-be alakitani a file tartalmat my $hashref = ${xml_2_hash($tree, 'top')}{'top'}; %agents = %{$hashref}; # agenslista verzioszam beallitasa, ezzel lehet osszehasonlitani masoket $agent_list_ver = $agents{'data'}{'agent_list_ver'}; # ezutan mar csak az agensek adataira van szukseg %agents = %{$agents{'data'}{'agent_list'}}; log_err_deb("Agenslista verzio: $agent_list_ver, lista: agents), 0, 0, 3);
" . Dumper(\%
# a fonok kikeresese $im_boss = 1; foreach $item (keys(%agents)) { if($agents{$item}{'pri'} > $agents{$config{'self'}{'id'}}{'pri'}) { $im_boss = 0; @fact = ("'boss($item)'", "i_am_not_boss"); }; }; if($im_boss) { @fact = ("'boss(".$config{'self'}{'id'}.")'", "i_am_boss"); }; return (\@fact, ['init_agent'], []);
};
# egy egyszeru alkalmazasa a rendszernek # servereken futo alkalmazasokat figyel, riportol, es logol # alkalmas a serverek karbantartoinak a riasztasara sub action_server_test { my @fact; my @nfact; if(! $server_test_config{'logfile'}) { require "server_test_config.pl" or log_err_deb("Server test konfig file nem megnyithato $!", 0, 1, 1); # sajat logfile megnyitasa open(STL, ">>" . $server_test_config{'logfile'}); }; foreach $item (keys(%{$server_test_config{'servers'}})) { # kivalasztott server pingelese use Net::Ping; # ping objektum letrehozasa
20
# icmp hasznalata csak root-nak engedelyezett # igy csak ilyen futtatas eseten hasznaljuk $ping = Net::Ping->new($> ? "tcp" : "icmp") or print (STL log_line("Nem sikerült ping objektumot létrehozni $!")); if($ping->ping($server_test_config{'servers'}{$item}{'host'})) { print (STL log_line("a " . $server_test_config{'servers'}{$item} {'host'} . " elérhető")); } else { print (STL log_line("a " . $server_test_config{'servers'}{$item} {'host'} . " pingelese sikertelen")); }; $ping->close(); # kivalasztott server ftp szolgaltatasanak tesztelese use Net::FTP; if($ftp = Net::FTP->new($server_test_config{'servers'}{$item} {'ftp_domain'}, Timeout => $server_test_config{'servers'}{$item}{'ftp_timeuot'}, Debug => $server_test_config{'servers'}{$item}{'ftp_debug'})) { print (STL log_line($server_test_config{'servers'}{$item} {'ftp_domain'} . " ftp szolgáltatás elérhető")); } else { print (STL log_line($server_test_config{'servers'}{$item} {'ftp_domain'} . " ftp szolgáltatás nem elérhető")); }; # kivalasztott server web szolgaltatasanak tesztelese $wget_logfile = "tmp/" . $server_test_config{'servers'}{$item}{'web_site'} . ".wget_log.txt"; $wget_outfile = "tmp/" . $server_test_config{'servers'}{$item} {'web_site'}; system($server_test_config{'wget'} . " -o $wget_logfile -O $wget_outfile -T " . $server_test_config{'servers'}{$item}{'web_timeout'} . " " . $server_test_config{'servers'}{$item}{'web_site'}); open(WL, $wget_logfile); while(<WL>) { $wget_log .= $_; }; close(WL); if($wget_log =~ /connected\./) { print (STL log_line("A " . $server_test_config{'servers'}{$item} {'web_site'} . " lekereses sikeres")); if($server_test_config{'servers'}{$item}{'www_pattern'}) { # Sikeres lekeres utan ellenorizheto hogy nem cserelte ki e az oldalt illetektelen behatolo. # Ezt az oldalba szurt allando karakterlanc keresesevel tehetjuk meg. # A karakterlancot az oldal tulajdonosa valtoztatas eseten is az oldalban hagyja. # A karakterlanc egyszeruseg kedveert egy sorban helyezkedik el $changed = 1; open(WO, $wget_outfile); while(<WO>) { $changed = 0 if(/$server_test_config{'servers'}{$item} {'www_pattern'}/x); }; close(WO); if($changed) { print (STL log_line("A " . $server_test_config{'servers'}{$item} {'web_site'} . " -ot megváltoztatták"));
21
} else { print (STL log_line("A " . $server_test_config{'servers'}{$item} {'web_site'} . " változatlan")); }; }; } else { # sikertelen a weboldal lekérése print (STL log_line("A " . $server_test_config{'servers'}{$item} {'web_site'} . " lekereses sikertelen")); # ebben az esetben riasztjuk az oldal operatorat push(@fact, "'send_mail(" . $config{'operator_mail'} . ")(" . $server_test_config{'servers'}{$item}{'host_operator'} . ")(automatikus riasztas)(Rendszerunk szerint laallt a kovetkezo oldal szolgaltatasa: " . $server_test_config{'servers'}{$item}{'web_site'} . ")'"); }; }; return(\@fact, \@nfact, []);
};
################################################################################ # elorecsomagolt tenyhalmazok melyekkel az agenst indithatjuk ################################################################################ # a legminimalisabb minta tenyhalmaz # hatasara elindul es leall az agens sub f_r_0 { # facts # # ami mindig igaz $p->add_fact("'true'"); # sleep minimalisra allitasa $p->add_fact("'sleep_null'"); # az agens elindult $p->add_fact("'agent_started'"); # szukseg van az inicializalasra $p->add_fact("'init_agent'");
}
# rules # # egybol alljon le ha elindult $p->add_fact("stop_agent => 'agent_started'"); # alvas tiltas $p->add_fact("'NOT sleepr' => 'sleep_null'");
# levelkuldesi tenyhalmaz # elkuld egy levelet az operatornak. sub f_r_send_mail { # facts # # ami mindig igaz $p->add_fact("'true'"); # sleep minimalisra allitasa $p->add_fact("'sleep_null'");
22
# az agens elindult $p->add_fact("'agent_started'"); # szukseg van az inicializalasra $p->add_fact("'init_agent'");
}
# rules # # egybol alljon le ha elindult $p->add_fact("'send_mail(neurotic)(neurotic)(subject)(message)'"); $p->add_fact("'send_mail(neurotic)(neurotic)(masik subject)(masik message)'"); # alvas tiltas $p->add_fact("'NOT sleepr' => 'sleep_null'");
# szamlalo tenyhalmaz # hatasara az agens novel egy szamlalot sub f_r_tik_tak { # facts # # ami mindig igaz $p->add_fact("'true'"); # sleep minimalisra allitasa $p->add_fact("'sleep_min'"); # az agens elindult $p->add_fact("'agent_started'"); # szukseg van az inicializalasra $p->add_fact("'init_agent'"); # szamlalo inicializalasa $p->add_fact("tik_tak");
}
# rules # # egybol alljon le ha elindult # $p->add_fact("stop_agent => 'agent_started'"); # alvas tiltas $p->add_fact("'NOT sleepr' => 'sleep_null'"); # noveljuk a szamlalot $p->add_fact("tik_tak => 'tik_tak(v_1)'");
# ido lekerdezo tenyhalmaz # hatasara az agens: # ha alacsony prioritasu: lekerdezi az idot, majd leall # ha fonok : megvalaszolja az idot sub f_r_get_time { # facts # $p->add_fact("'true'"); $p->add_fact("'sleep_min'"); $p->add_fact("'agent_started'"); $p->add_fact("'init_agent'"); # rules # # ha mi vagyunk a kliens akkor le kell kerni az idot $p->add_fact("get_time => 'i_am_not_boss'");
23
}
# ha megkaptuk mar az idot, akkor nem kell tobbet lekerni $p->add_fact("'NOT get_time' => 'time_got(v_1)'"); # ha lekertuk az idot, akkor mindenki leallhat $p->add_fact("stop_agent => 'time_sent'"); # $p->add_fact("stop_agent => 'time_got(v_1)'"); # ha sleep null akkor torolni kell a sleep szabalyokat $p->add_fact("'NOT sleepr' => 'sleep_null'");
# agenslista lekerdezo tenyhalmaz # hatasara az alacsonyabb prioritasu agens # lekeri a frissebb agenslistat a fonoktol # es aktualizalja azzal sajatjat sub f_r_get_agent_list { # facts # $p->add_fact("'true'"); $p->add_fact("'sleep_min'"); $p->add_fact("'agent_started'"); $p->add_fact("'init_agent'");
}
# rules # # ha mi vagyunk a kliens akkor le kell kerni az agenslistat $p->add_fact("get_agent_list => 'i_am_not_boss'"); # ha lekertuk az agenslistat, akkor mindenki leallhat $p->add_fact("stop_agent => 'agent_list_sent'"); $p->add_fact("stop_agent => 'agent_list_got'"); # ha sleep null akkor torolni kell a sleep szabalyokat $p->add_fact("'NOT sleepr' => 'sleep_null'");
# szerver tesztelesi tenyhalmaz # hatasara az agens leteszteli a konfiguracios file-ban felsorolt # szervereken levo szolgaltatasokat sub f_r_server_test { # facts # $p->add_fact("'true'"); $p->add_fact("'sleep_min'"); $p->add_fact("'agent_started'"); $p->add_fact("'init_agent'");
}
# rules # # ha mi vagyunk a kliens akkor le kell kerni az agenslistat $p->add_fact("server_test");
################################################################################ # cselekvesek es jellemzoik betoltese ################################################################################ # ez az eljaras betolti a cselekvesek sub load_actions { foreach $item (keys(%actions)) {
jellemzoit a tenyhalmazba
24
# tuzelesi feltetelek felvetele a szabalyokhoz foreach $cond (split(/ /, $actions{$item}{'cond'})) { $p->add_fact("'$item' => '$cond'"); }; # tuzeles-tiltasi feltetelek felvetele a szabalyokhoz foreach $ncond (split(/ /, $actions{$item}{'n-cond'})) { $p->add_fact("'NON $item' => '$ncond'"); };
};
};
Server.pl #!/usr/bin/perl ################################################################################ ### # Biztositja az agens szamara a server kornyezetet # Elinditja, megallitja az agenst, logokat kezel ################################################################################ ### # megallapitjuk hol vagyunk a filerendszerben use FindBin qw($Bin); # beallitjuk a segedfileok konyvtarat use lib "$Bin/lib"; # osszetett strukturak kiiratasanak eszkoze use Data::Dumper; # XML osszeallito eszkoz use XML::Writer; # XML ertelmezo eszkoz use XML::Parser; # szukseges eszkozok beolvasasa require "config.pl"; require "mmas.pl"; require "actions.pl"; require "$Bin/lib/server_misc.pl"; require "$Bin/lib/communicator_misc.pl"; require "$Bin/lib/propose_misc.pl"; require "$Bin/lib/xml_misc.pl"; # use strict; use POSIX; # mit tegyunk ? 25
if($ARGV[0] eq 'start') { start(); } elsif($ARGV[0] eq 'stop') { stop(); } elsif($ARGV[0] eq 'status') { status(); } elsif($ARGV[0] eq 'restart') { stop(); start(); } else { print "usage: command [start | stop | restart | status] \n"; }; # az eljaras demonkent futtathatova teszi az agenst. # igy folyamatosan futhat a hatterben sub daemon { use IO::Socket; use IO::Select; use Socket; use Fcntl; use Tie::RefHash; # port lefoglalasa $server = IO::Socket::INET->new(LocalPort => $config{'self'}{'peer_port'}, Listen => $config{'max_conn'}) or die "Couldn't start server at port " . $config{'self'}{'peer_port'} . " : $@ \n"; # demonkent valo futtatas beallitasai if($config{'daemon_mode'}) { # atlepes a sajat konyvtarba chroot($config{'dir'}); # uj session inditasa $session_id = POSIX::setsid() or die "Can't start a new session: $!\n"; # STD kapcsolatok megszakitasa close(STDIN); close(STDOUT); close(STDERR); }; log_err_deb("Server started", 1, 0, 1); # kommunkacios bufferek uritese %inbuffer = (); %outbuffer = (); %ready = (); %kill = (); 26
tie(%ready, 'Tie::RefHash'); # szerver nonblock modba allitasa # egyszerre tobb kapcsolat kezelesehez nonblock($server); $select = IO::Select->new($server); # agens kornyezet inditasa mmas(); # agens pusztulasakor a server leallitasa close ($server); };
communicator_misc.pl #!/usr/bin/perl ################################################################################ ####### # kommunikaciohoz szukseges eljarasok gyujtemenye ################################################################################ ####### # a kommunikacios foeljaras sub communicate { my $client; my $rv; my $data;
# megnezzuk van e valami olvasnivalo foreach $client ($select->can_read(1)) { if($client == $server) { # uj kapcsolat fogadasa $client = $server->accept(); $select->add($client); nonblock($client); } else { # adat olvasasa $data = ''; $rv = $client->recv($data, POSIX::BUFSIZ, 0); unless(defined($rv) && length $data) { # file vege: kliens lekapcsolasa 27
kill_client($client); next; }; $inbuffer{$client} .= $data; # meg kell nezni hogy vege van e a request-nek while ($inbuffer{$client} =~ s/(.*\n)//) { push( @{$ready{$client}}, $1); } } } # teljes keresek kezelese foreach $client (keys %ready) { handle_request($client); }; # ha kepzodott valasz a kerdesre, akkor azt el kell kuldeni es megszakitani a kapcsolatot foreach $item (keys(%query)) { # ha mar kesz a valasz, akkor el kell kuldeni a kliensnek es leszakitani if($query{$item}{'answer'}) { $outbuffer{$query{$item}{'client'}} = $query{$item}{'answer'}; $kill{$query{$item}{'client'}} = 1; delete($query{$item}); }; }; # kiirando bufferek foreach $client ($select->can_write(1)) { # semmit se mondunk annak akinek nincs mit mondanunk next unless exists $outbuffer{$client}; # az uzenet megvalaszololasa is xml-ben tortenik, a lekeresnel megszokott adatokkal my $answer = "$agent_list_ver<xml_ver>" . $config{'xml_ver'} . "" . $config{'agent_ver'} . "" . $outbuffer{$client} . "<self>" . $config{'self'}{'id'} . "<pri>" . $agents{$config{'self'}{'id'}}{'pri'} . ""; # valasz kuldesi kiserlet $rv = $client->send($answer, 0); unless (defined $rv) { # sikertelen uzenetkuldes log_err_deb("Ugy volt hogy tudok irni de megsem $client", 0, 2, 3); next; }; if($rv == length $outbuffer{$client} || 28
$! == POSIX::EWOULDBLOCK) { # sikeres uzenetkuldes substr($outbuffer{$client}, 0, $rv) = ''; delete $outbuffer{$client} unless length $outbuffer{$client}; # itt helyben bontjuk a kapcsolatot a klienssel, a masodik (kikommentezett) esetben kesobb bontanank # de az nem mukodik megbizhatoan kill_client($client); # $kill{$client} = 1; } else { # nem lehet kiirni az osszes adatot, es nem blokkolas miatt -> kliens kapcsolat megszakitasa delete $inbuffer{$client}; delete $outbuffer{$client}; delete $ready{$client}; $select->remove($client); close($client); next; } }; # kivalasztott kliensek leszakitasa foreach $client (keys %kill) { kill_client($client); }; # rossz adatok foreach $client ($select->has_exception(0)) { # time out es egyeb hibak eseten }; }; ## beerkezett uzenetek kezelese #sub handle_request { # # a lekerdezesek a $ready{$client}-ben vannak # my $client = shift; # my $request; # foreach $request (@{$ready{$client}}) { # # $request: a lekerdezes szovege # # # # XML uzenetekben kommunikalunk, ezert inicializalunk egy parsert # $parser = new XML::Parser( Style => 'Tree' ); # my $tree = $parser->parse($request); # # feldolgozzuk a kerest 29
# my $hashref = ${xml_2_hash($tree, 'top')}{'top'}; # # ki kell boviteni a tenyhalmazt a kerdessel # $p->add_fact("'query_" . ${$hashref}{'request'}{'query'}{'qstr'} . "'"); # # fel kell jegyezni hogy erkezett ilyen keres egy klienstol # $query{'query_' . ${$hashref}{'request'}{'query'}{'qstr'}}{'client'} = $client; # }; # delete $ready{$client}; #};
# kapcsolat megszakitasa kliensel sub kill_client { my $client = shift; # minden bufferbol toroljuk a kliens adatait delete $inbuffer{$client}; delete $otbuffer{$client}; delete $ready{$client}; delete $kill{$client}; # kapcsolat megszakitasa $select->remove($client); close $client or log_err_deb("ERROR closing $client : $!", 0, 1, 3); }; # parhumzamos kapcsolatok megvalositasa sub nonblock { my $socket = shift; my $flags; $flags = fcntl($socket, F_GETFL, 0) or die "Can't get flags for socket: $! \n"; fcntl($socket, F_SETFL, $flags | O_NONBLOCK) or die "Can't make socket nonblocking: $!\n"; }; sub send_mail { # sending mail :-) # parameters : from, to, subject, message # open(MAIL, "|" . $config{'send_mail'} . " -t " . $config{'send_mail_user'}); print(MAIL "From: $_[0]\n"); print(MAIL "To: $_[1]\n"); print(MAIL "Subject: $_[2]\n\n"); 30
print(MAIL "$_[3] \n"); close(MAIL); } # masik agenstol informaciot kero eljaras sub q_agent { ($aid, $qstr) = @_; # az agens eleresehez szukseges informaciok $socket = IO::Socket::INET->new(PeerAddr => $agents{$aid}{'peer_addr'}, PeerPort => $agents{$aid}{'peer_port'}, Proto => 'tcp', Type => SOCK_STREAM) or log_err_deb("Couldn't connect to " . ":" . " : $@", 0, 1, 1); # a lekerdezes adatai, melyeket XML-ben kuld az agens a masiknak $access_request = { 'request' => { 'self' => { 'id' => $config{'self'}{'id'}, 'pri' => $agents{$config{'self'}{'id'}}{'pri'} }, 'header' => { 'agent_ver' => $config{'agent_ver'}, 'xml_ver' => $config{'xml_ver'}, 'agent_list_ver' => $agent_list_ver }, 'query' => { 'qstr' => $qstr } } }; # az informaciok XML-be kodolasa es kuldese write_hash_2_xml($access_request, \$socket); # valasz lekerese $reply = <$socket>; close ($socket); $parser = new XML::Parser( Style => 'Tree' ); my $tree = $parser->parse($reply); # feldolgozzuk a kerest my $hashref = ${xml_2_hash($tree, 'top')}{'top'}; # # ha mar kommunikaltunk, akkor ellenorizzuk hogy nem kell e uj informaciokat letolteni # # meg kell nezni, es ha a masik agensnek magasabb a prioritasa, es ujabb az agenslistaja # akkor frissiteni kell az agenslistat 31
if(${$hashref}{'reply'}{'header'}{'agent_list_ver'} > $agent_list_ver && ${$hashref}{'reply'}{'self'}{'pri'} > $agents{$config{'self'}{'id'}}{'pri'}) { log_err_deb("Automatikus agenslistafrissites inditasa", 1, 0, 1); # tenyhalmaz bovitese az agenslista lekeresehez szukseges tenyekkel $p->add_fact("get_agent_list => 'i_am_not_boss'"); # ha lekertuk az agenslistat, akkor mindenki leallhat # $p->add_fact("stop_agent => 'agent_list_sent'"); $p->add_fact("stop_agent => 'agent_list_got'"); }; # meg kell nezni, es ha a masik agensnek magasabb a prioritasa, es ujabb az agens verzioszama # akkor frissiteni kell az agenst. Ezt az operatornak irt figyelmezteto levellel tehetjuk meg. if(${$hashref}{'reply'}{'header'}{'agent_ver'} > $config{'agent_ver'} && ${$hashref}{'reply'}{'self'}{'pri'} > $agents{$config{'self'}{'id'}}{'pri'}) { log_err_deb("Figyelmeztetes kuldese az operatornak frissebb agens verziorol", 1, 0, 1); # tenyhalmaz bovitese az agenslista lekeresehez szukseges tenyekkel $p->add_fact("'send_mail(" . $config{'operator_mail'} . ")(" . $config{'operator_mail'} . ") (Frissebb agens letezik)(Egy magasabb prioritasu agenssel valo kommunikacio soran kiderult hogy ujabb agens verzio letezik mar.)'"); #$p->add_fact("'send_mail(neurotic)(neurotic)(subject)(message)'"); }; return $hashref; } # beerkezett kereseket kezelo eljaras sub handle_request { # a keresek a $ready{$client} hash-ben vannak my $client = shift; my $request; foreach $request (@{$ready{$client}}) { # $request a lekerdezes szovege # a valasz az $outbuffer{$client}-be kerul # # az XML feldolgozo inicializalasa $parser = new XML::Parser( Style => 'Tree' ); # az XML feldolgozas my $tree = $parser->parse($request); my $hashref = ${xml_2_hash($tree, 'top')}{'top'}; # ki kell boviteni a tenyhalmazt a kerdessel $p->add_fact("'query_" . ${$hashref}{'request'}{'query'}{'qstr'} . "'"); # fel kell jegyezni hogy erkezett ilyen keres egy klienstol $query{'query_' . ${$hashref}{'request'}{'query'}{'qstr'}}{'client'} = $client; }; # ha kepzodott valasz a kerdesre, akkor azt el kell kuldeni es megszakitani a kapcsolatot foreach $item (keys(%query)) { 32
if($query{$item}{'answer'}) { $outbuffer{$query{$item}{'client'}} = $query{$item}{'answer'}; delete($query{$item}); $kill{$query{$item}{'client'}} = 1; }; }; delete $ready{$client}; };
xml_misc.pl #!/usr/bin/perl ############################################################################### # xml hasznalathoz eljarasgyujtemeny ###############################################################################
# file desriptorba kiir egy xml-e alakitott hasht sub write_hash_2_xml { my ($hash, $output) = @_; $writer = new XML::Writer(OUTPUT => $$output, UNSAFE => 1, NEWLINE => 1); hash_2_xml($hash); $writer->end(); }; # egy hash-bol xml stringet keszit # rekurizvan hivja magat, mig az egesz kesz nincs # visszateresi erteke egy referencia a kesz hash-re sub hash_2_xml { my ($hash) = @_; if(ref($hash) eq "HASH") { foreach my $item (keys(%{$hash})) { # osszetett tartalom kiirasa # # nyitotag $writer->startTag($item); # tartalom hash_2_xml($$hash{$item}); 33
# zarotag $writer->endTag($item); }; } else { # sima karaktersorozat kiirasa $writer->characters($hash); } } # xml atalakitasa hash-be # rekurzivan vegigmegy a tartalmon sub xml_2_hash { my ($aref, $parent) = @_; my $array = ''; my $scalar = ''; my $debug = 0; my %ret = (); my $returned; foreach $item (@{$aref}) { if(ref($item) eq "HASH") { } elsif(ref($item) eq "ARRAY") { $array = $item; } else { $scalar = $item; } if($scalar && $array) { #%ret = (%ret, %{xml_2_hash($array, $scalar)}); $returned = xml_2_hash($array, $scalar); foreach $item2 (keys(%{$returned})) { $ret{$parent}{$item2} = ${$returned}{$item2}; }; $array = ''; $scalar = ''; }; }; if ($scalar && !$array) { $ret{$parent} = $scalar; }; return \%ret; }
34
To-Do lista Ebben a listában kapnak helyet a rendszer továbbfejlesztésével kapcsolatos legfontosabb ötletek. • Professzionálisabb következtető rendszer használata Mivel a következtető rendszer határozza meg az ágensek működését, ezért annak erőssége sokkal nagyobb szabadságot enged meg a felhasznált következtetési szabályok összetettebbségén keresztül. • Kifinomultabb futtató eljárás használata A futtató eljárás választja ki az ágens számára a végrehajtandó cselekvéseket. A cselekedetekhez kapcsolt prioritások, vagy más jellemzők kihasználásával hatékonyabb ágens készíthető. • Összetettebb akciók fejlesztése gyakorlati fehlasználásra A jelenlegi rendszerben implementált funkciók magának a rendszernek a működéséhez fontosak, illetve példaként szolgálhatnak új akciók fejlesztéséhez. A meglevő keretek és példák segítségével könnyen fejleszthetőek olyan akciók melyek hasznos funkciókkal látják el a rendszert. Például a megosztott rendszer kihasználásaként készíthető olyan cselekvés gyűjtemény mellyel az ágensek egy hálózat működését figyelik.
35
Futtatás kimenete Az alábbiakban egy példa futtatás kimenete szerepe. A példafuttatás leírása megtalálható a fejlesztői dokumentációban, a számlálás és ágenslista lekérés pont alatt. A további kimenetek a felhasználói dokumentáció által leírt helyen találhatóak. [ [ [ [ [ [ [ [
Fri Fri Fri Fri Fri Fri Fri Fri
Jun Jun Jun Jun Jun Jun Jun Jun
27 27 27 27 27 27 27 27 [
16:24:16 16:24:16 16:24:16 16:24:16 16:24:16 16:24:16 16:24:16 16:24:16
2003 2003 2003 2003 2003 2003 2003 2003
] ] ] ] ] ] ] ]
Starting Server Checking Server Status: No running Server found Server started Checking Server Status: Server run: 8238 Server started $VAR1 = [
'true'
], [
'sleep_min'
], [
'agent_started'
], [
'init_agent'
], [
'tik_tak'
], [
'NOT sleepr', 'sleep_null'
], [
'tik_tak', 'tik_tak(v_1)'
], [
'true'
], [
'sleep_min'
], [
'agent_started'
], [
'init_agent'
], [
'get_agent_list', 'i_am_not_boss'
],
36
[
'stop_agent', 'agent_list_sent'
], [
'stop_agent', 'agent_list_got'
], [
'NOT sleepr', 'sleep_null'
], [
'get_agent_list', 'get_agent_list'
], [
'send_agent_list', 'query_get_agent_list'
], [
'get_time', 'get_time'
], [
'tik_tak', 'tik_tak'
], [
'send_time', 'query_get_time'
], [
'init_agent', 'init_agent'
], [
'sleepr', 'sleep_min'
], [
'sleepr', 'sleep_mid'
], [
'sleepr', 'sleep_max'
], [ ]
'NON sleepr', 'sleep_null'
];
[ Fri Jun 27 16:24:16 2003 ] Inditas [ Fri Jun 27 16:24:16 2003 ] Visszateres [ Fri Jun 27 16:24:16 2003 ] Inditas
tik_tak (Novel egy szamlalot) 'tik_tak(1)' :: tik_tak() :: init_agent (Inicializalja az agenst.)
37
[ Fri Jun 27 16:24:16 2003 ] Agenslista 'agent_1' => { 'peer_addr' => 'peer_port' => 'pri' => '100' }, 'agent_2' => { 'peer_addr' => 'peer_port' => 'pri' => '55' } };
verzio: 2, lista:
$VAR1 = {
'127.0.0.1', '1999',
[ Fri Jun 27 16:24:16 2003 ] Visszateres init_agent :: [ Fri Jun 27 16:24:16 2003 ] Inditas idore) [ Fri Jun 27 16:24:17 2003 ] Visszateres [ Fri Jun 27 16:24:19 2003 ] Tenyhalmaz 'true' => '1', 'sleep_min' => '1', 'tik_tak' => '1', 'sleepr' => '1', 'init_agent' => '1', 'agent_started' => '1' };
'127.0.0.1', '1998',
'boss(agent_1)' i_am_not_boss :: sleepr (Pihenteti az agenst egy :: :: $VAR1 = {
[ Fri Jun 27 16:24:19 2003 ] Inditas get_agent_list (Lekeri az agens listat a legmagasabb prioritasutol) [ Fri Jun 27 16:24:23 2003 ] Agenslista aktualizalasa, uj adat: 2127.0.0. 11999<pri>100127.0.0.11998<pri>55127.0.0.11997<pri>33 [ Fri Jun 27 16:24:23 2003 ] Visszateres 'init_agent' 'agent_list_got' :: get_agent_list :: [ Fri Jun 27 16:24:23 2003 ] Inditas tik_tak (Novel egy szamlalot) [ Fri Jun 27 16:24:23 2003 ] Visszateres 'tik_tak(2)' :: tik_tak(1) :: [ Fri Jun 27 16:24:23 2003 ] Inditas sleepr (Pihenteti az agenst egy idore) [ Fri Jun 27 16:24:24 2003 ] Visszateres :: :: [ Fri Jun 27 16:24:26 2003 ] Tenyhalmaz $VAR1 = { 'get_agent_list' => '1', 'i_am_not_boss' => '1', 'tik_tak(1)' => '1', 'true' => '1', 'sleep_min' => '1', 'tik_tak' => '1', 'sleepr' => '1', 'boss(agent_1)' => '1', 'agent_started' => '1' }; [ Fri Jun 27 16:24:27 2003 ] Inditas listat a legmagasabb prioritasutol)
get_agent_list (Lekeri az agens
38
[ Fri Jun 27 16:24:31 2003 ] Agenslista aktualizalasa, uj adat: 2127.0.0. 11999<pri>100127.0.0.11998<pri>55127.0.0.11997<pri>33 [ Fri Jun 27 16:24:31 2003 ] Visszateres 'init_agent' 'agent_list_got' :: get_agent_list :: [ Fri Jun 27 16:24:31 2003 ] Inditas tik_tak (Novel egy szamlalot) [ Fri Jun 27 16:24:31 2003 ] Visszateres 'tik_tak(3)' :: tik_tak(2) :: [ Fri Jun 27 16:24:31 2003 ] Inditas init_agent (Inicializalja az agenst.) [ Fri Jun 27 16:24:31 2003 ] Agenslista verzio: 2, lista: $VAR1 = { 'agent_1' => { 'peer_addr' => '127.0.0.1', 'peer_port' => '1999', 'pri' => '100' }, 'agent_2' => { 'peer_addr' => '127.0.0.1', 'peer_port' => '1998', 'pri' => '55' }, 'agent_3' => { 'peer_addr' => '127.0.0.1', 'peer_port' => '1997', 'pri' => '33' } }; [ Fri Jun 27 16:24:31 2003 ] Visszateres init_agent :: [ Fri Jun 27 16:24:31 2003 ] Inditas idore) [ Fri Jun 27 16:24:32 2003 ] Visszateres [ Fri Jun 27 16:24:34 2003 ] Tenyhalmaz 'get_agent_list' => '1', 'i_am_not_boss' => '1', 'tik_tak(2)' => '1', 'true' => '1', 'agent_list_got' => '1', 'sleep_min' => '1', 'stop_agent' => '1', 'tik_tak' => '1', 'sleepr' => '1', 'init_agent' => '1', 'boss(agent_1)' => '1', 'agent_started' => '1' };
'boss(agent_1)' i_am_not_boss :: sleepr (Pihenteti az agenst egy :: :: $VAR1 = {
[ Fri Jun 27 16:24:34 2003 ] Checking Server Status: [ Fri Jun 27 16:24:34 2003 ] Server run: 8238
39