You are on page 1of 36

CORBA

Poetkom 90-ih je bilo otean razvoj mrenih aplikacija. Od mnogobrojnih razloga navodimo samo neke: Razliit hardver raunara Razliita mrena oprema Razliiti mreni protokoli Razliiti operativni sistemi Razliiti programski jezici Sa ciljem da premosti jaz izmeu programa koji su bili pisani na razliitim programskim jezicima, izvravali se na raunarima na kojima su trali razliiti operativni sistemi, koji su bili povezani preko razliitih mrenih tehnologija korienjem razliitih mrenih protokola, nastao je standard CORBA Common Object Request Broker Architecture. CORBA je prvi, najvaniji i pre svega najambiciozniji middleware projekat pokrenut u istoriji. Proizvod je konzorcijuma OMG (Object Management Group) koji broji preko 700 lanova (to pojedinaca to velikih softverskih kompanija). CORBA je papir, tj. specifikacija na preko hiljadu strana.

Istorijat
Verzija 1.0 Datum izlaska okt. 1991 Opis - CORBA objektni model - Osnovni API - Mapiranje na programski jezik C - IDL (Interface Definition Language) jezik za opis interfejsa - Interface repository - interfejsi za BOA (Basic Object Adapter) - interfejsi za rukovanje memorijom - pojasnili objektni model

1.1

feb. 1992

1.2 2.0

dec. 1993 aug. 1996

- zadrali postojei objektni model - podrka za C++ i Smalltalk - protokoli za komunikaciju: GIOP (General Inter-ORB Protocol), IIOP (Internet Inter-ORB Protocol) - poveana bezbednost: sigurni IIOP i IIOP over SSL - podrka za Ada i COBOL programske jezike - POA (Portable Object Adapter) - poveava portabilnost servera - komunikacija sa DCOM-om - podrka za programski jezik Java

2.1

aug. 1997

2.2

feb. 1998

2.3

jun. 1999

2.4

okt. 2000

mapiranje IDL-a na programski jezik Java mapiranje na C++ portabilnost IDL/Java interoperabilni naming servis minimalna CORBA (Minimum CORBA) CORBA za rad u realnom vremenu (Real-time CORBA)

2.5

sep 2001

- Fault tolerant CORBA specifikacija - Portable interceptors - Common Security - CORBA Core specifikacija - CORBA Component model - Minimum i Real-time CORBA postaju odvojene specifikacije

2.6 3.0

dec. 2001 jul. 2002

3.0.3 mar. 2004 - samo da se vidi da je CORBA iva Tabela 1. Istorijat CORBA-e CORBA je bila veoma popularna sredinom devedesetih, pre nagle ekspanzije Internet-a. OMG je sporo reagovao (pre svega zbog velikog broja lanova) i nisu na vreme odgovorili na zahteve trita koje se preorijentisalo prema web-u i zbog toga su bili pregaeni. Razlozi zbog kojih CORBA nije postala ono za ta je bila namenjena lee u sledeim injenicama: - skup razvoj aplikacija - CORBA esto suvie komplikovana - mnoge implementacije su pune raznih propusta (bug-ovi, sigurnosne rupe, itd.) Glavni razlog polakog posustajanja CORBA-e je nedovoljno brzo praenje zahteva trita. Tritu je bio potreban otvoren standard koji bi omoguio komunikaciju izmeu razliitih aplikacija kroz otvoreni Internet. CORBA komunikacija koristi vie portove i zato ne prolazi kroz vatrene zidove (firewall). Bez obzira to su CORBA poruke bile binarne i iz tog razloga su se prenosile jako brzo, prva tehnologija koja je znaajnije zapretila CORBA-i je bila SOAP (Simple Object Access Protocol), koji je izdat 1999. godine. SOAP koristi XML poruke koje se lako prenose Internet-om i itljive su i za raunare i za ljude. Iako su XML poruke tekstualne, to znai da koliina prenetih podataka nije optimalna, SOAP je brzo nadirao zbog lakoe upotrebe i lakog prolaenja kroz Internet (korienjem HTTP protokola bez problema prolazi kroz veinu firewall-ova). Sledei dogaaj koji je isto doprineo gubitku trinog uea je bio kada se 2000. i 2001. izduvao Internet balon i kada su mnoge kompanije koje su koristili CORBA-u nestale sa trita. Danas CORBA ima jako mali deo trinog uea, bez obzira na njene mnogobrojne pozitivne karakteristike.

Primena
CORBA je specifikacija koja teoretski dozvoljava da dva CORBA programa komuniciraju bez ikakvih promena iako su: - pisana na razliitim programskim jezicima (npr. C++ i Java) - izvravaju se na razliitim operativnim sistemima (npr. Windows i UNIX)

koriste razliite mrene protokole (npr. TCP/IP i Modbus) izvravaju se na razliitom hardveru (npr. Intel 32 bitni procesori i Alpha procesori) koriste razliite mrene tehnologije (npr. 100 Mbps Ethernet i token ring mrea)

Na ovako sloene zahteve CORBA odgovara tako, to se useli izmeu operativnog sistema i aplikacije i sakrije sloenost operativnog sistema (a zajedno sa OS-om sakriva sloenost mrenih protokola, hardvera raunara i mrenog hardvera). CORBA je izbor onih, kojima je potrebna brzina i nezavisnost od isporuioca hardvera, proizvoaa operativnog sistema i/ili mrene tehnologije. Oni koji se odlue za CORBA-u ne moraju da trpe politiku proizvoaa kada doe do prelaska na sledeu verziju operativnog sistema/hardvera. Kada odreeni OS ili hardver postane nedostupan, CORBA bazirane aplikacije se uz neznatne modifikacije mogu preneti na drugi hardver/operativni sistem. Kod CORBA-e se podaci prenose binarno. Ovakav tip prenosa je puno bri od prenosa tekstualnih sadraja (npr. XML poruke kod SOAP-a). CORBA danas jedino na tritu embedded sistema ima porast trinog uea. Sem te oblasti postoje instalacije u: - rezervacije avio karata - komunikacija izmeu e-commerce aplikacija - telefonskim kompanijama (transakcije) - finansijskim sistemima

Implementacije
Kao to je ve ranije reeno, CORBA je samo papir, tj. specifikacija na vie od hiljadu stranica teksta. Ova specifikacija je bila ispred svog vremena kada je izala (poetkom devedesetih godina dvadesetog veka) i softverska zajednica je sa entuzijazmom prihvatila ovaj novi standard. Krenulo se u pisanje veeg broja implementacija. Implementacija je fizika realizacija CORBA specifikacije koja radi na jednom ili vie operativnih sistema i/ili na odreenoj hardverskoj platformi. Poznatije CORBA specifikacije su prikazane u tabeli 2. Ime CORBA verzija omniORB 2.6 TAO 3.0 ORBit2 2.4 MICO 3.0 IIOP.NET 2.3 Visibroker 2.6 orbacus 2.6 ... Tabela 2. CORBA implementacije Licenca LGPL GPL LGPL LGPL LGPL komercijalna komercijalna

Tabela 2. sadri implementacije sa otvorenim kodom (sa razliitim licencama) i dve komercijalne implementacije. Na katedri za Automatiku i upravljanje sistemima koriste se omniORB i TAO. IIOP.NET je moda najinteresantniji projekat iz tabele, jer je pisan u za .NET framework, bazira se na .NET remoting-u i omoguava komunikaciju izmeu .NET, CORBA i J2EE objekata.

Arhitektura

Slika 1. Opta arhitektura CORBA-e Prikazana slika je relativno loa, ali se najvaniji elementi lepo vide: Object impl server. Preciznije: serverski objekat Client klijent, koristi usluge servera Object Request Broker sloj koji sedi na operativnom sistemu i sakriva njegovu sloenost ORB Interface API preko koga i klijent i server pristupaju ORB-u IDL Skeleton kod dobijen prevoenjem IDL-a. Mapiranje tipova (tzv. marshaling) i bazne klase koje serverski objekat treba da implementira - IDL Stubs poput IDL Skeleton-a, slui za mapiranje tipova - Object adapter poveava portabilnost serverske implementacije jer omoguave pisanje koda servera koji je nezavisan od koriene CORBA implementacije Postoje dve verzije object adapter-a: BOA (Basic Object Adapter) i POA (Portable Object Adapter)

POA je novijeg datuma i praktino razdvaja implementaciju serverskog objekta od objekta koji obrauje zahteve (servant) Od svih objekata sa slike 1., programer koji radi na razvoju CORBA aplikacije pie samo klijenta i implementaciju serverskog objekta.

Instalacija omniORB-a
Postupak instalacije binarne distribucije se sastoji od skidanje omniORB instalacije sa Internet-a raspakivanja ZIP fajla koji sadri binarnu distribuciju i podeavaja sistemske promenljive PATH, dodavanjem putanje do omnioORB-ovog /bin direktorijuma

Kao i veina projekata sa otvorenim kodom, i pre svega projekata koji se piu sa ciljem da bi radili na veem broju operativnih sistema, i omniORB distribucija ima konvencionalnu strukturu direktorijuma. Ova organizacija direktorijuma je prikazana na slici broj 2.

Slika 2. Organizacija direktorijuma kod omniORB-a Najvaniji direktorijumi sa slike broj 2 su: ./bin izvrni fajlovi i DLL-ovi sa implementacijom CORBA-e (za Windows OS) ./doc dokumentacija ./idl IDL fajlovi sa definicijom interfejsa za primere koji dolaze sa instalacijom ./include header fajlovi implementacije (u ovom sluaju omniORB-a) i primera ./lib biblioteke ./src izvorni kod omniORB-a i primera

Podeavanje Naming Service-a


CORBA Naming Service je u okviru projekta omniORB implementiran u omniNames-u. omniNames se nalazi u ./bin folderu instalacije i mogue je njegovo pokretanje iz komandne linije (kucanjem komande omniNames). Za ispravno funkcionisanje ove komponente je potrebno uraditi sledea podeavanja (koja su opisana u datoteci Readme.Win32.txt u korenom direktorijumu omniORB-a): 1. pokrenuti Registry klju sample.reg koji se nalazi u korenu omniORB-a 2. otvoriti komandni (DOS) prozor i u njemu kucati (C:\temp po potrebi zameniti drugim folderom) set OMNINAMES_LOGDIR=C:\temp 3. pokrenuti alat za editovanje Registry baze (Start Run... regedit) i na putanji HKEY_LOCAL_MACHINE SOFTWARE omniORB InitRef definisati novu tekstualnu vrednost sa imenom 1 i vrednou NameService=corbaname::localhost 4. kod prvog pokretanja pokrenuti omninames sa start opcijom svako sledee pokretanje treba da ide bez opcije start (inae e se omniNames buniti) omniNames je mesto gde se CORBA serveri registruju, i odakle CORBA klijenti dobijaju reference na servere. Zbog toga on mora da bude pokrenut pre svih klijenata i servera i ne sme se zatvarati u toku rada.

Podeavanje Visual Studia 6 za rad sa omniORB-om


Detaljno uputstvo za podeavanje VS 6 razvojnog okruenja za rad sa omniORB-om se nalazi u datoteci README.win32.txt. Uputstvo se sastoji od sledeih koraka: 1. podeavanje opcija razvojnog okruenja: otvori se Tools Options i pod tab-om Directories definiu se dve putanje: a. do omniORB-ovih header fajlova (direktorijum ./include) b. do omniORB-ovih lib fajlova (iz combo box-a se izabere opcija Library files i podesi se da pokazuje na ./lib/x86_win32 (videti sliku 3.)

Slika 3. Putanja do omniORB ./include direktorijuma 2. podeavanje projekata: projekti moraju da budu Win32 konzolne aplikacije. Otvori se podeavanja projekta sa ALT+F7 ili Project Settings (slika 4.). Iz padajueg menija u gornjem levom delu prozora, gde na slici pie Win32 Debug se izabere opcija All configurations

U ovom prozoru se podeavaju sledee stvari:

a. na C/C++ tab-u: i. pod kategorijom C++ Language se omogui rad sa izuzecima (selektuje se Enable exception handling ii. pod kategorijom Code generation za run-time biblioteku sa bira Multithreaded DLL (videti sliku 4.) iii. pod kategorijom Preprocessor se do-definiu (poslednje dve za Win XP i 2000) ,__WIN32__, __x86__, _WIN32_WINNT=0x0400, __NT__, __OSVERSION__=4 b. na Link tab-u: i. pod kategorijom Input se dodaju sledee biblioteke posle ve definisanog niza biblioteka (paziti da je potrebno razdvojiti ove biblioteke od ve postojeih u tom polju sa razmakom): ws2_32.lib mswsock.lib advapi32.lib omniORB406_rt.lib omniDynamic406_rt.lib omnithread31_rt.lib

Podeavanje je potrebno malo modifikovati za Debug konfiguraciju, i to u skladu sa sledeim uputstvom: - na C/C++ tabu, pod Code generation za run-time biblioteku birati Multi-threaded debug DLL - na Link tabu, u kategoriji Input se dodaju sledee biblioteke (debug verzije omniORB biblioteka): ws2_32.lib mswsock.lib omnithread31_rtd.lib advapi32.lib omniORB406_rtd.lib omniDynamic406_rtd.lib

Vano je napomenuti da se i novije verzije Visual Studio razvojnih okruenja (2003 i 2005) nametaju na slian nain.

Prevoenje prvog echo primera


Prvi zadatak jeste da se definie IDL opis interfejsa servera i da se on prevede. IDL se nalazi u istoimenom direktorijumu omniORB-a, i zove se echo.idl. Njegov je sadraj sledei: interface Echo { string echoString(in string mesg); }; IDL se mora prevesti na onaj programski jezik na kojem se planira pisanje implementacije servera. Kod prvog echo primera je to C++. Prevoenje na C++ se radi sa IDL prevodiocem koji dolazi sa omniORB-om. On se zove omniidl, nalazi se u ./bin direktorijumu i poziva se na sledei nain: omniidl -bcxx -Wbh=.h -Wbs=SK.cpp -Wbd=DynSK.cpp -Wbexample echo.IDL Opcije koje su bile prosleene IDL prevodiocu su sledee: - bcxx definisanje ciljnog programskog jezika: u ovom sluaju C++ - Wbh ekstenzija header fajlova skeletona - Wbs i Wbd ekstenzija izvornih fajlova skeletona - Wbexample kreiranje koda sa primerom Pre nego to se pree na prevoenje IDL fajla, potrebno je da se on prekopira iz ./IDL direktorijuma na mesto prevoenja echo primera, tj. iz ./idl u ./src/examples/echo. Nakon pokretanja omniidl prevodioca, ako je sve prolo kako treba, dobijaju se 4 datoteke: - echo.h skeleton, zaglavlje sa klasama potrebnim za implementaciju serverskog objekta - echoSK.cpp skeleton - echoDynSK.cpp skeleton - echo_i.cc primer prazne implementacije serverske klase Ne treba koristiti primer koji je dobijen prevoenjem IDL-a, on je ovde samo da bi bilo pokazano da je sam omniidl u stanju da napravi primer implementacije serverskog objekta. U ovom trenutku je potrebno napraviti novi, prazan projekat u Visual Studio-u 6. Tip projekta treba da bude Win32 Console Application (videti sliku). U prazan projekat se dodaju skeleton fajlovi dobijeni prevoenjem IDL-a, tj. echo.h, echoSK.cpp, echoDynSK.cpp. Sa definisanim skeletonom imamo vezu sa ORB-om. Sve to je jo potrebno da se uradi, jeste da se definie implementacija serverskog objekta. Kod ovog prvog primera e biti koriena gotova implementacija serverskog objekta koja se nalazi u datoteci eg1.cc, u direktorijumu ./src/examples/echo

Pre nego to se doda, datoteka eg1.cc se mora preimenovati u eg1.cpp. Ovo se radi iz razloga to je podrazumevano ponaanje VS6 da samo datoteke sa cpp ekstenzijom tumai kao izvorni kod. Posle preimenovanja i dodavanja datoteke eg1.cpp se moe prei na prevoenje prvog primera. Prevodioc e verovatno prijaviti par greaka zbog pogrenih imena fajlova (npr. u kodu u datoteci eg1.cpp se referencira datoteka echo.hh umesto echo.h). Popraviti ove greke i potom pokrenuti prvi echo primer. Dobija se sledei odziv:

Tumaenje koda
Implementacija servera i klijenta se kod ovog primera nalaze u istom EXE fajlu. I klijent i server su implementirani u datoteci eg1.cpp. - class Echo_i implementacija servera sa praznim konstruktorom i destruktorom i implementacijom metode echoString - metoda hello ova metoda simulira ponaanje klijenta: na ulazu dobija referencu na serverski objekat i na njemu poziva metodu echoString - metoda main inicijalizacija ORB-a, kreiranje serverskog objekta i njegova aktivacija na Portable Object Adapter-u (POA-i)

Prevoenje drugog echo primera


Drugi echo primer razdvaja implementaciju klijenta i servera u dva EXE fajlova. Da bi se ovo postiglo, potrebno je napraviti dva projekta u VS6. Imena tih projekata neka budu: - echo2_server - echo2_client Tip ova dva projekta isto treba da bude Win32 Console Application. Ova dva projekta se dodaju u isti workspace gde se nalazi projekat prvog primera. Oba ova projekta se moraju podesiti na isti nain kao to je to raeno kod prvog echo primera. Najlake i najbre podeavanje ova dva projekta jeste da se podeavanja kopiraju izmeu projekata. Ovo se radi tako to se u prozoru za podeavanje projekta selektuju dva novo dodata projekta (videti sliku) i za njih se zajedno definiu podeavanja koja su definisana za prvi echo primer. U oba ova projekta se dodaju skeleton fajlovi. Samo e se implementacije razlikovati. U klijentski projekat se dodaje fajl eg2_clt.cpp dok se u serverski projekat dodaje eg2_impl.cpp.

Na slici iznad se vidi koji treba da bude sadraj ova dva projekta. Takoe se vidi i deo koda implementacije servera. Klasa je ve poznata iz prvog primera, kao i njegova jedina (neprazna) metoda echoString. U main metodi se aktivira serverski objekat i ispie se njegov IOR (Interoperable Object Reference). Ovaj IOR je (neitljiv) jedinstveni identifikator servera. U njemu je kodirana IP adresa, port i ime servera. Svakim pokretanjem servera se dobija drugi IOR, jer svaka instanca istog servera dobija jedinstven IOR. Pokree se server (nakon popravljanja eventualnih greaka i prevoenja) i dobija se odziv poput onog na slici ispod.

Kao to se na slici vidi, nakon pokretanja, serverski EXE ispisuje jedinstveni IOR instance serverskog objekta. Klijentu se mora proslediti ovaj IOR da bi mogao da se povee na server. Pre prosleivanja se IOR mora kopirati iz komandnog prozora u tekst editor i potrebno je obrisati svaki prelazak u novi red i apostrofe sa poetka i kraja. Tako se dobija string koji izgleda otprilike ovako: IOR:010000000d00000049444c3a4563686f.......3136382e302e37002505 Klijent se poziva iz komandnog prozora tako to se navede njegovo ime i prosledi mu se serverov IOR. Nakon pritiska na dugme Enter, klijent treba da se povee na server i da pozove serverovu metodu echoString. Odziv klijenta je prikazan na slici ispod.

Tumaenje koda drugi Echo primer


Kao to je ve reeno, kod ovog primera se klijent i server nalaze u odvojenim adresnim prostorima, u dva odvojena izvrna programa (EXE-a). Sadraj C++ datoteke sa implementacijom servera (eg2_impl.cpp) se malo razlikuje u odnosu na prethodni primer: - sadri klasu Echo_i koja implementira interfejs servera. Ova klasa ima prazan konstruktor i destruktor i implementira metodu echoString (koja vraa kopiju stringa) - metoda hello je izbaena jer je ona glumila ulogu klijenta - novo u main metodi (u odnosu na prethodni primer) je pretvaranje serverskog objekta u IOR sa pozivom orb->object_to_string(...) 1. CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); 2. CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); 3. PortableServer::POA_var poa = PortableServer::POA::_narrow(obj); 4. Echo_i* myecho = new Echo_i(); 5. PortableServer::ObjectId_var myechoid = poa->activate_object(myecho); 6. // Obtain a reference to the object, and print it out as a 7. // stringified IOR. 8. obj = myecho->_this(); 9. CORBA::String_var sior(orb->object_to_string(obj)); 10. cerr << "'" << (char*)sior << "'" << endl; 11. myecho->_remove_ref(); 12. PortableServer::POAManager_var pman = poa->the_POAManager(); 13. pman->activate(); 14. orb->run(); Listing 1. Sadraj main metode iz datoteke eg2_impl.cpp Red Opis 1 inicijalizacija CORBA-e 2-3 dolaenje do Portable Object Adapter-a (POA) 4-5 kreiranje serverskog objekta i njegova aktivacija na POA-i 8-10 pretvaranje reference u IOR i ispis 11 brisanje lokalne reference na serverski objekat 12-13 aktivacija POA Manager-a 14 pokretanje Tabela 3. Kratak opis koda iz listinga 1.

Tumaenje koda - drugi Echo primer - klijent


1. CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); 2. 3. 4. 5. if( argc != 2 ) { cerr << "usage: eg2_clt <object reference>" << endl; return 1; }

6. CORBA::Object_var obj = orb->string_to_object(argv[1]); 7. Echo_var echoref = Echo::_narrow(obj); 8. if( CORBA::is_nil(echoref) ) { 9. cerr << "Can't narrow reference to type Echo (or it was nil)." << endl; 10. return 1; 11. } 12. for (CORBA::ULong count=0; count<10; count++) 13. hello(echoref); 14. orb->destroy(); Listing 2. Main metoda klijenta Opis inicijalizacija CORBA provera da li je EXE pozvan sa odgovarajuim brojem parametara dolaenje do serverske reference na osnovu IOR-a (argv[1]) pretvaranje reference u Echo tip provera da li je uspelo dolaenje do reference i cast-ovanje u for petlji se deset puta poziva metoda hello koja poziva echoString metodu na serverskoj referenci Tabela 4. Opis main metode klijenta datoteka eg2_clt.cpp Red 1 2-5 6 7 8-11 12-13

Trei echo primer


Trei primer, slino drugom, razdvaja adresne prostore klijenta i servera, tj. prave se dva izvrna fajla. Ova dva primera se razlikuju utoliko to se u treem ne koristi neitljiv IOR za ostvarivanje klijent-server veze, nego se koristi Naming servis. Ovaj servis slui za mapiranje jedinstvenih serverskih IOR-ova na itljive stringove. Postupak je slian kao kod drugog primera: - u istom, ve otvorenom workspace-u naprave se dva prazna projekta tipa Win32 Console Application. Imena projekata nek budu: echo3_server i echo3_client - oba projekta se podese na isti nain kao i za prethodna dva primera - u oba projekta se dodaju skeleton fajlovi (echo.h, echoSK.cpp i echoDynSK.cpp) - u klijentski projekat se doda datoteka eg3_clt.cpp - u serverski projekat se doda datoteka eg3_impl.cpp - oba projekta se prevedu - pokrene se omniORB-ov Naming servis koji se zove omninames. On se pokree tako to se otvori novi komandni prozor i u njemu se ukuca omninames

Tumaenje koda - server


1. CORBA::ORB_var orb = CORBA::ORB_init(argc, argv) ; 2. CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); 3. PortableServer::POA_var poa = PortableServer::POA::_narrow(obj); 4. Echo_i* myecho = new Echo_i(); 5. PortableServer::ObjectId_var myechoid = poa->activate_object(myecho); 6. bindObjectToName(orb, obj) ; 7. myecho->_remove_ref(); 8. PortableServer::POAManager_var pman = poa->the_POAManager(); 9. pman->activate(); 10. orb->run(); Listing 3. Koda pojednostavljene main metode servera (datoteka eg3_impl.cpp) Red Opis 1-3 inicijalizacija CORBA-e i dolaenje do Portable Object Adapter-a (POA) 4-5 kreiranje serverskog objekta i njegova aktivacija na POA-i 6 poziv metode bindObjectToName koja registruje serverski objekat 7-10 brisanje reference, aktivacija POA Manager-a i pokretanje Tabela 5. Opis koda iz listinga 2. Metoda bindObjectToName registruje serverski objekat na Naming Service-u (tj. omniNames-u). U ovom primeru je ime pod kojim se serverski objekat registruje hard kodiran u test/Echo (test je kontekst, Echo je ime objekta). Ova metoda se u datoteci eg3_impl.cpp nalazi ispod main metode. Modifikovana verzija ove metode se moe nai u dodatku A (sa dodatna dva ulaza). Ako iz nekog razloga nije omoguen pristup Windows Registry-ju, i zbog toga nije omoguen unos putanje do omniNames-a u isti, onda se svaki server i klijent pokreu sa opcijom iz komandne

linije koja im govori gde se nalazi omniNames, tj. za neki server server1 bi poziv iz komandne linije izgledao ovako:
server1 -ORBInitRef NameService=corbaname::localhost

Umesto adrese localhost (lokalna maina) moe da se stavi simboliko ime ili IP adresa bilo koje druge dostupne mrene lokacije gde je pokrenut omniNames.

Tumaenje koda klijent


1. CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); 2. CORBA::Object_var obj = getObjectReference(orb, "Test", "Echo"); 3. Echo_var echoref = Echo::_narrow(obj); 4. for (CORBA::ULong count=0; count < 10; count++) 5. hello(echoref); 6. orb->destroy();

Listing 4. Koda pojednostavljene main metode klijenta (datoteka eg3_clt.cpp) Red Opis 1 inicijalizacija CORBA-e 2 dolaenje do reference na serverski objekat pozivom getObjectReference 3 pretvaranje u Echo tip 4-5 10 poziva preko ranije upoznate metode hello Tabela 6. Opis koda iz listinga 4.

Detaljno uputstvo za izradu CORBA projekata


Opti koraci izrade CORBA projekata u razvojnom okruenju Visual C++ 6: I. II. III. IV. V. VI. VII. instalacija CORBA-e u sluaju binarne distribucije omniORB-a se ovo svodi na otpakivanje ZIP datoteke na disku podeavanje sistema kreiranje novog projekta Win32 Console Application ako se projekat radi u RC-u, onda nek se on snimi na mreni (S:) disk pisanje i snimanje IDL-a ovaj korak je mogue uraditi kako u razvojnom okruenju tako i u Notepad-u ili bilo kom drugom editoru za tekst prevoenje IDL-a ako se koristi omniORB, onda se ovo svodi na pozivanje omniidl-a sa opcijama koje su ranije objanjene. Prevoenjem IDL-a nastaje tzv. skeleton. skeleton ukljuiti u projekat koji je kreiran u treem koraku server) ako je napravljena prazna implementacija servera onda samo obrisati sadraj linija koje poinju sa #warning i umesto njih ukucati minimalnu implementaciju servera klijent) ako se radi sa IOR-om, onda iskoristiti eg2_clt.cpp kao polaznu taku, ako se radi sa omniNames-om, onda iskoristiti eg3_clt.cpp kao polaznu taku podesiti projekat prevesti projekat i pokrenuti aplikaciju za pokretanje se predlae otvaranje novog DOS prozora sa Start Run cmd pa navigiranjem do Debug/Release direktorijuma aplikacije (klijenta ili servera) pokrenuti aplikaciju ako server radi sa IOR-om, onda oistiti IOR i proslediti ga klijentu kroz komandnu liniju ako server radi sa omniNames-om, onda ga pokrenuti sa odgovarajuom opcijom iz komandne linije koja govori serveru gde da trai omniNames

VIII. IX.

X.

Dok se koraci I-II rade samo jednom, ostale korake je potrebno uraditi za CORBA projekte (kako servere tako i klijente). Korak X se podrazumevao na vebama i nije bio pisan.

Rad sa nitima
Rad se nitima (thread) u projektima koji ukljuuju funkcionalnost omniORB-a se omoguava ukljuenjem header datoteke omnithread.h. Preduslov za ovo je da se radi o CORBA projektu koji koristi omniORB (jer gornji header dolazi sa omniORB-om). Do potrebe za uvoenjem vie niti izvravanja programa dolazi kada - ima vie klijenata koji se istovremeno kae na server - se izvravaju izuzetno zahtevni prorauni na raunarima sa vie procesora/jezgara - itd. Za rad sa nitima je potrebno napraviti klasu tipa nit, kreirate primerak te klase i pokrenuti. Na taj nain e se omoguiti izvravanje veeg broja niti u paraleli.
class WorkerThread : public omni_thread { public: WorkerThread(int nid, const STransfer& trans) : m_id(nid), m_trans(trans) {} ~WorkerThread() {} void Start(void) { start_undetached(); } private: void* run_undetached(void*); int m_id; const STransfer& m_trans; }; void* WorkerThread::run_undetached(void*) { cout << "Thread ID=" << m_id << " - Working..." << endl; Sleep(5000); cout << "Thread ID=" << m_id << " - Done." << endl; return 0; }

Listing 8. Deklaracija i definicija klase koja implementira jednu nit


WorkerThread* pworker = new WorkerThread(m_nThreadNumber++, trans); pworker->Start();

Listing 9. Korienje ranije definisane niti Kod programa koji rade sa vie niti koji rade sa istim podacima moe doi do nekonzistentnosti podataka. Ovo se izbegava zakljuavanjem. Postoje mnogi naini zakljuavanja podataka. Ovde emo prikazati zakljuavanje sa mutex-om.
Finance::STransfers* Finance_ITransfer_i::GetAllTransfers(const char* strAccount){ m_mutex.lock(); cout << "GetAllTransfers received" << endl; STransfers* pTrans = new STransfers(); pTrans->length(m_vTransfers.size()); for (int i=0; i<m_vTransfers.size(); i++)

{ (*(pTrans))[i] = m_vTransfers[i]; } m_mutex.unlock(); return pTrans; }

Listing 10. Metoda koja koristi mehanizam zakljuavanja (mutex - metode lock i unlock)

Dodatni primer #1
Implementirati CORBA server sa interfejsom Validator koji se sastoji od sledeih metoda: Ime metode Ulazi validateDate string strDate validateNumber string strNumber Tabela 7. Metode servera Validator Izlaz(i) bool bool

Implementirati klijenta koji e se kaiti na server i pozivati metode servera. Reenje: Prvo se definie IDL opis interfejsa Validator. On se sastoji od dve metode i definie se u datoteci validator.idl (videti listing). Ovaj IDL se potom prevodi na C++ sa sledeim pozivom:
omniidl bcxx Wbh=.h Wbs=SK.cpp -Wbexample validator.idl

Prevoenjem IDL datoteke se dobija skeleton koji povezuje na kod sa ORB-om. Nakon pokretanja gore navedene komande nastaju fajlovi: - validator.hh preimenovati u validator.h - validator.cc Sa istoimenim header fajlom ini skeleton. Preimenovati u validator.cpp. - validator_i.cc promeniti ekstenziju u cpp. Poto je koriena opcija Wbexample, IDL prevodioc e izgenerisati i primer, tj. serversku klasu sa praznim metodama. Ove metode je potrebno implementirati. #ifndef __VALIDATOR_IDL__ #define __VALIDATOR_IDL__ interface Validator { boolean validateDate(in string strDate); boolean validateNumber(in string strNumber); }; #endif // __VALIDATOR_IDL__ Listing 5. IDL opis interfejsa Validator

Dodatni primer #2
Implementirati CORBA server koji ima sledea dva interfejsa Ulazi int nFileLength int nDays writeLine string strMessage TestMonitor init int interval monitorAlive string strIPAddress monitorMemUse Tabela 8. Metode servera TestTrace i TestMonitor Interfejs TestTrace Ime metode init Izlaz(i) bool int (MB)

Interfejse definisati u istom IDL fajlu. Prevoenjem se dobija prazna implementacija servera (pod uslovom da se IDL prevodiocu prosledi opcija Wbexample). Prazna implementacija se sastoji od klasa TestTrace_i i TestMonitor_i. Njihove metode se moraju implementirati (barem da vrate vrednost ako je to potrebno i da ispiu neku poruku). Zadaci: - implementirati server koji implementira oba interfejsa iz tabele 8. Server treba da ispie IOR obe serverskog objekta. Minimalna implementacija metode treba da se sastoji od ispisa poruke koja identifikuje metodu i od linije koja vraa vrednost (ako metoda vraa vrednost) - implementirati klijenta koji se kai na jedan od gornja dva interfejsa i poziva barem jednu metodu - promeniti server da registruje oba serverska objekta na omniNames-u. Koristiti modifikovanu bindObjectToName metodu iz Dodatka A (na kraju ovog dokumenta). - promeniti klijenta da se kai na oba serverska interfejsa. Klijent treba da dolazi do referenci preko omniNames-a. Treba da pozove barem jednu metodu oba interfejsa. Koristiti modifikovanu metodu getObjectReference iz dodatka A sa kraja ovog dokumenta

Dodatni primer #3
Implementirati CORBA server koji je opisan IDL-om iz listinga 6. Server da se registruje na omniNames-u sa imenom Example.Date. Napisati CORBA klijentsku aplikaciju koja poziva sve metode servera. Za komunikaciju sa omniNames-om koristiti modifikovane metode iz ove skripte. module DateService { struct MDate { long year; short month; short day; short hour; short minute; short second; long millisecond; }; typedef sequence<MDate> MDateSequence; typedef sequence<boolean> booleanSequence; exception DateError { string reason; }; interface IDateValidator { boolean ValidateDate(in MDate date) raises(DateError); booleanSequence ValidateDates(in MDateSequence dates) raises(DateError); }; interface IDateConversion { MDateSequence GetDatesBetween(in MDate begin, in MDate end) raises(DateError); MDate ToDate(in string strDate) raises(DateError); string ToString(in MDate date) raises(DateError); }; }; Listing 6. IDL opis modula DateService Sledei koncepti su novi u IDL listingu 6:

1. moduli slue za grupisanje veeg broja IDL tipova i interfejsa. Za definisanje modula se koristi kljuna re module (poetak spiska) 2. strukture za definisanje sloenih podataka koji se sastoje od osnovnih tipova (long, float, string, itd.) i drugih struktura. Za definisanje struktura se koristi kluna re struct. 3. nizovi u CORBA IDL-u se niz definie kljunom reju sequence. U listingu 6 se definiu dve sekvence: niz struktura tipa Mdate i niz boolean promenljivih 4. izuzeci znaajna razlika izmeu CORBA-e i COM-a jeste mogunost korienja izuzetaka u klijent-server vezi kod CORBA-e. Podseanja radi, kod COM-a se dojava greaka realizuje slanjem celobrojnih kodova (HRESULT). Izuzetak (engl. exception) se baci na serveru, propagira se kroz CORBA-u i hvata se na klijentu u catch bloku.

Dodatni primer #4
Implementirati CORBA server koji je opisan IDL-om iz listinga 7. Server da se registruje na omniNames-u sve svoje interfejse (npr. ImeModula.ImeInterfejsa). Napisati CORBA klijentsku aplikaciju koja poziva sve metode servera. Za komunikaciju sa omniNames-om koristiti modifikovane metode iz ove skripte.
module Finance { enum ECurrency {E_DINAR, E_EURO, E_POUND}; struct SDateTime { short nYear; short nMonth; short nDay; short nHour; short nMinute; short nSecond; }; struct STransfer { string strFrom; string strTo; ECurrency eCurr; float fValue; SDateTime dtDate; }; typedef sequence<STransfer> STransfers; interface ITransferCallback { void TransferMade(in STransfer trans); }; exception TransferException { string strReason; }; interface ITransfer { void DoTransfer(in STransfer trans); STransfers GetAllTransfers(in string strAccount); STransfers GetTransfers(in string strAccount, in SDateTime dtFrom, in SDateTime dtTo); STransfers GetTransfersByCurrency(in string strAccount, in ECurrency eCurr); void SetTransferCallback(in ITransferCallback callback); };

struct SPerson { long nId; string strFirsname; string strLastname;

string strAddress; string strCity; string strPostcode; }; exception AccountException { string strReason; }; interface IAccount { long CreateAccount(in SPerson person) raises(AccountException, TransferException); }; };

Listing 7. IDL opis servera

Dodatni primer #5
Za interfejs iz listinga 8 a) napraviti CORBA serversku aplikaciju koja implementira interfejs IWarehouse. Napraviti CORBA klijentsku aplikaciju, koja izigrava proizvodnu liniju, i prima dojave preko interfejsa IAssemblyCallback. Server da implementira brojae svih tipova delova vozila (karoserija, toak, motor) i da ih aurira unutar metoda za uzimanje i dodavanje delova (GetPart i PutPart, respektivno). Klijent da periodino preuzima delove iz skladita i da pravi vozila (npr. svakih 10 sekundi) b) napraviti CORBA klijentsku aplikaciju koja prima dojave preko interfejsa IAssemblyCallback i u trenutku nestanka nekog dela poalje odreeni broj tih delova u skladite. c) prepraviti klijenta iz zadatka a) da pokree tri niti, i da svaka nit periodino preuzima delove i pravi vozila
module VehicleFactory { enum EPart { E_BODY, E_WHEEL, E_MOTOR }; // assembly lines are clients who receive callbacks through this interface interface IAssemblyCallback { void NoParts(in EPart eType); // no more parts left }; // the warehouse is the server supplying assembly lines with parts interface IWarehouse { void GetPart(in EPart eType); void PutPart(in EPart eType, in long count); void SetCallback(in IAssemblyCallback assembly); }; };

Listing 8. Opis interfejsa skladita i proizvodne linije (klijenta)

Reenja
Na serveru uraditi sledee: - snimiti IDL, prevesti ga i ukljuiti skeleton u projekat - promeniti ekstenziju automatski generisane implementacije servera u .cpp i ukljuiti ga u projekat - prepraviti server da radi sa omniNames-om, tj. ukljuiti header datoteku sa sadrajem iz dodatka A i umesto ispisa IOR-a pozvati bindObjectToName - u glavnoj (main) metodi - definisati novi tip vektora za skladitenje tipa IAssemblyCallback_ptr (pokaziva na objekte tipa IAssemblyCallback) i u klasu koja implementira interfejs IWarehouse dodati jedan primerak tog vektora - u metodi SetCallback implementirati ubacivanje kopije dobijenog pokazivaa u skladite, tj. u vektor definisan u prethodnom koraku - u klasu koja implementira interfejs IWarehouse dodati tri promenljive tipa ceo broj (int) za brojanje trenutnog stanja na lageru (broja delova) obavezno ih inicijalizovati u konstruktoru klase

ako broj preostalih delova padne na vrednost ispod 1, onda poslati dojave svim klijentima da je nestao taj deo

Na klijentu uraditi sledee: - za polaznu taku izabrati kod klijenta iz prethodnog primer (Finance_clt.cpp) promeniti ime datoteke u AssemblyLine_clt.cpp) - izbaciti klasu (i njene metode) koja implementira interfejs ITransferCallback iz prethodnog primera i umesto nje ubaciti klasu koja implmenetira interfejs IAssemblyCallback - prepraviti sve pozive i tipove u main metodi svuda staviti odgovarajua imena namespace-ova i klasi - napraviti beskonanu petlju koja uzima delove iz skladita (tj. poziva metodu GetPart na serveru) u petlju ubaciti Sleep od 10 sekundi Na klijentu za b) uraditi sledee: - napraviti novi projekat, prevesti IDL i ukljuiti skeleton u projekat - za polaznu taku iskoristiti klijenta iz prethodnog primera - prepraviti jedninu metodu callback interfejsa da pored ispisa imena metode uradi i slanje delova odgovarajueg tipa preko metode PutPart poslati proizvoljan broj delova. Prilog B sadri kod servera i klijenata za a) i b). Dodatni klijent pod c) uraditi samostalno.

Dodatak A Header datoteka za rad sa omniNames-om


#include <iostream> #include <omniORB4/CORBA.h> using namespace std; static CORBA::Boolean bindObjectToName(CORBA::ORB_ptr orb, CORBA::Object_ptr objref, char* pcContext, char* pcName) { CosNaming::NamingContext_var rootContext; try { CORBA::Object_var obj = orb->resolve_initial_references("NameService"); rootContext = CosNaming::NamingContext::_narrow(obj); if( CORBA::is_nil(rootContext) ) { cerr << "Failed to narrow the root naming context." << endl; return 0; } } catch(CORBA::ORB::InvalidName& ex) { cerr << "Service required is invalid [does not exist]." << endl; return 0; } try { CosNaming::Name contextName; contextName.length(1); contextName[0].id = (const char*) pcContext; // string copied contextName[0].kind = (const char*) "my_context"; // string copied CosNaming::NamingContext_var testContext; try { testContext = rootContext->bind_new_context(contextName); } catch(CosNaming::NamingContext::AlreadyBound& ex) { CORBA::Object_var obj; obj = rootContext->resolve(contextName); testContext = CosNaming::NamingContext::_narrow(obj); if( CORBA::is_nil(testContext) ) { cerr << "Failed to narrow naming context." << endl; return 0; } } // Bind objref with name Echo to the testContext: CosNaming::Name objectName; objectName.length(1); objectName[0].id = (const char*) pcName; // string copied objectName[0].kind = (const char*) "Object"; // string copied try { testContext->bind(objectName, objref); } catch(CosNaming::NamingContext::AlreadyBound& ex) { testContext->rebind(objectName, objref); } } catch(CORBA::COMM_FAILURE& ex) { cerr << "Caught system exception COMM_FAILURE -- unable to contact the "

<< "naming service." << endl; return 0; } catch(CORBA::SystemException&) { cerr << "Caught a CORBA::SystemException while using the naming service." << endl; return 0; } return 1; }

static CORBA::Object_ptr getObjectReference(CORBA::ORB_ptr orb, char* pcContext, char* pcName) { CosNaming::NamingContext_var rootContext; try { CORBA::Object_var obj = orb->resolve_initial_references("NameService"); rootContext = CosNaming::NamingContext::_narrow(obj); if( CORBA::is_nil(rootContext) ) { cerr << "Failed to narrow the root naming context." << endl; return CORBA::Object::_nil(); } } catch(CORBA::ORB::InvalidName& ex) { cerr << "Service required is invalid [does not exist]." << endl; return CORBA::Object::_nil(); } // Create a name object, containing the name test/context: CosNaming::Name name; name.length(2); name[0].id = (const char*) pcContext; // string copied name[0].kind = (const char*) "my_context"; // string copied name[1].id = (const char*) pcName; name[1].kind = (const char*) "Object"; try { return rootContext->resolve(name); } catch(CosNaming::NamingContext::NotFound& ex) { cerr << "Context not found." << endl; } catch(CORBA::COMM_FAILURE& ex) { cerr << "Caught system exception COMM_FAILURE -- unable to contact the " << "naming service." << endl; } catch(CORBA::SystemException&) { cerr << "Caught a CORBA::SystemException while using the naming service." << endl; } return CORBA::Object::_nil(); }

Dodatak B kod za dodatni primer br. 5


Kod servera:
#include #include #include #include <iostream> <vector> "VehicleFactory.h" "../../omniidl_helper.h"

using namespace VehicleFactory; using namespace std; typedef vector<IAssemblyCallback_ptr> CallbackVector;

class VehicleFactory_IWarehouse_i: public POA_VehicleFactory::IWarehouse { private: // brojaci preostalih delova int nBodies; int nWheels; int nMotors; // skladiste callback objekata CallbackVector m_vCallbacks; void NotifyClients(EPart eType); public: VehicleFactory_IWarehouse_i(); virtual ~VehicleFactory_IWarehouse_i(); // methods corresponding to defined IDL attributes and operations void GetPart(VehicleFactory::EPart eType); void PutPart(VehicleFactory::EPart eType, ::CORBA::Long count); void SetCallback(VehicleFactory::IAssemblyCallback_ptr assembly); }; // konstruktor klase VehicleFactory_IWarehouse_i::VehicleFactory_IWarehouse_i(){ nBodies = 2; nWheels = 6; nMotors = 3; } VehicleFactory_IWarehouse_i::~VehicleFactory_IWarehouse_i(){ } void VehicleFactory_IWarehouse_i::GetPart(VehicleFactory::EPart eType){ cout << "Metoda GetPart - za delove tipa: " << eType << endl; switch (eType) { case E_BODY: if (nBodies > 0) nBodies--; else NotifyClients(E_BODY); break; case E_WHEEL: if (nWheels > 0) nWheels--;

else NotifyClients(E_WHEEL); break; case E_MOTOR: if (nMotors > 0) nMotors--; else NotifyClients(E_MOTOR); break; } } void VehicleFactory_IWarehouse_i::PutPart(VehicleFactory::EPart eType, ::CORBA::Long count){ cout << "Metoda PutPart - za delove tipa: " << eType << endl; cout << " - primljeno ukupno " << count << " delova." << endl; switch (eType) { case E_BODY: nBodies += count; break; case E_WHEEL: nWheels += count; break; case E_MOTOR: nMotors += count; break; } } void VehicleFactory_IWarehouse_i::SetCallback(VehicleFactory::IAssemblyCallback_ptr assembly){ cout << "Metoda SetCallback." << endl; m_vCallbacks.push_back(VehicleFactory::IAssemblyCallback::_duplicate(assembly )); } void VehicleFactory_IWarehouse_i::NotifyClients(EPart eType) { cout << "Slanje obavestenja da nema vise delova tipa: " << eType << endl; for (int i = 0; i < m_vCallbacks.size(); i++) { // mora try-catch zbog visecih callback objekata try { m_vCallbacks[i]->NoParts(eType); } catch (...) { } } }

int main(int argc, char** argv) { try { // Inicijalizacija CORBA-e CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // pristup POA-i CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);

// Kreiranje CORBA objekta u memoriji sa operatorom new VehicleFactory_IWarehouse_i* myVehicleFactory_IWarehouse_i = new VehicleFactory_IWarehouse_i(); // Aktiviranje CORBA objekta na POA-i PortableServer::ObjectId_var myVehicleFactory_IWarehouse_iid = poa>activate_object(myVehicleFactory_IWarehouse_i); // Registrovanje CORBA objekta na omniNames-u { CORBA::Object_var ref = myVehicleFactory_IWarehouse_i->_this(); bindObjectToName(orb, ref, "VehicleFactory", "IWarehouse"); } // Pokretanje POA-e - od ovog trenutka CORBA servanti primaju pozive PortableServer::POAManager_var pman = poa->the_POAManager(); pman->activate(); orb->run(); orb->destroy(); } catch(CORBA::TRANSIENT&) { cerr << "Caught system exception TRANSIENT -- unable to contact the " << "server." << endl; } catch(CORBA::SystemException& ex) { cerr << "Caught a CORBA::" << ex._name() << endl; } catch(CORBA::Exception& ex) { cerr << "Caught CORBA::Exception: " << ex._name() << endl; } catch(omniORB::fatalException& fe) { cerr << "Caught omniORB::fatalException:" << endl; cerr << " file: " << fe.file() << endl; cerr << " line: " << fe.line() << endl; cerr << " mesg: " << fe.errmsg() << endl; } return 0; }

Listing 9. Kod servera deo reenja dodatnog zadatka 5a)

Kod klijenta pod a):


#include <Windows.h> #include "VehicleFactory.h" #ifdef HAVE_STD # include <iostream> # include <fstream> using namespace std; #else # include <iostream.h> #endif #include "../../omniidl_helper.h" using namespace VehicleFactory;

using namespace std; // klasa koja implementira callback interfejs IAssemblyCallback class VehicleFactory_IAssemblyCallback_i: public POA_VehicleFactory::IAssemblyCallback { private: public: VehicleFactory_IAssemblyCallback_i(); virtual ~VehicleFactory_IAssemblyCallback_i(); // implementacija metoda (callback) interfejsa void NoParts(VehicleFactory::EPart eType); }; VehicleFactory_IAssemblyCallback_i::VehicleFactory_IAssemblyCallback_i(){ } VehicleFactory_IAssemblyCallback_i::~VehicleFactory_IAssemblyCallback_i(){ } void VehicleFactory_IAssemblyCallback_i::NoParts(VehicleFactory::EPart eType){ cout << "Callback metoda NoParts." << endl; }

////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { try { // inicijalizacija CORBA-e CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // pristup POA-i CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa = PortableServer::POA::_narrow(obj); // pokretanje POA-e PortableServer::POAManager_var pman = poa->the_POAManager(); pman->activate(); // pristup serveru, tj. uzimanje reference CORBA::Object_var trobj = getObjectReference(orb, "VehicleFactory", "IWarehouse"); VehicleFactory::IWarehouse_var dref = VehicleFactory::IWarehouse::_narrow(trobj); if( CORBA::is_nil(dref) ) { cerr << "Can't narrow reference to type IWarehouse (or it was nil)." << endl; return 1; } // kreiranje i slanje callback objekta na server VehicleFactory_IAssemblyCallback_i* myVehicleFactory_IAssemblyCallback_i = new VehicleFactory_IAssemblyCallback_i(); PortableServer::ObjectId_var myVehicleFactory_IAssemblyCallback_iid = poa>activate_object(myVehicleFactory_IAssemblyCallback_i); dref->SetCallback(myVehicleFactory_IAssemblyCallback_i->_this()); // preuzimanje delova svakih 10 sekundi while (true) { try

{ dref->GetPart(E_BODY); dref->GetPart(E_MOTOR); for (int i=0; i<4; i++) dref->GetPart(E_WHEEL); Sleep(10000); } catch (...) { ; } } orb->run(); orb->destroy(); } catch(CORBA::TRANSIENT&) { cerr << "Caught system exception TRANSIENT -- unable to contact the " << "server." << endl; } catch(CORBA::SystemException& ex) { cerr << "Caught a CORBA::" << ex._name() << endl; } catch(CORBA::Exception& ex) { cerr << "Caught CORBA::Exception: " << ex._name() << endl; } catch(omniORB::fatalException& fe) { cerr << "Caught omniORB::fatalException:" << endl; cerr << " file: " << fe.file() << endl; cerr << " line: " << fe.line() << endl; cerr << " mesg: " << fe.errmsg() << endl; } return 0; }

Listing 10. Kod klijenta deo reenja dodatnog zadatka 5a)

Kod klijenta pod b):


#include <Windows.h> #include "VehicleFactory.h" #ifdef HAVE_STD # include <iostream> # include <fstream> using namespace std; #else # include <iostream.h> #endif #include "../../omniidl_helper.h" using namespace VehicleFactory; using namespace std; static bool bNoBodiesLeft = false;

static bool bNoMotorsLeft = false; static bool bNoWheelsLeft = false; // klasa koja implementira callback interfejs IAssemblyCallback class VehicleFactory_IAssemblyCallback_i: public POA_VehicleFactory::IAssemblyCallback { private: public: VehicleFactory_IAssemblyCallback_i(); virtual ~VehicleFactory_IAssemblyCallback_i(); // implementacija metoda (callback) interfejsa void NoParts(VehicleFactory::EPart eType); }; VehicleFactory_IAssemblyCallback_i::VehicleFactory_IAssemblyCallback_i(){ } VehicleFactory_IAssemblyCallback_i::~VehicleFactory_IAssemblyCallback_i(){ } void VehicleFactory_IAssemblyCallback_i::NoParts(VehicleFactory::EPart eType){ cout << "Callback metoda NoParts." << endl; switch (eType) { case E_BODY: bNoBodiesLeft = true; break; case E_WHEEL: bNoWheelsLeft = true; break; case E_MOTOR: bNoMotorsLeft = true; break; } }

////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { try { // inicijalizacija CORBA-e CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // pristup POA-i CORBA::Object_var obj = orb->resolve_initial_references("RootPOA"); PortableServer::POA_var poa = PortableServer::POA::_narrow(obj); // pokretanje POA-e PortableServer::POAManager_var pman = poa->the_POAManager(); pman->activate(); // pristup serveru, tj. uzimanje reference CORBA::Object_var trobj = getObjectReference(orb, "VehicleFactory", "IWarehouse"); VehicleFactory::IWarehouse_var dref = VehicleFactory::IWarehouse::_narrow(trobj); if( CORBA::is_nil(dref) ) { cerr << "Can't narrow reference to type IWarehouse (or it was nil)." << endl; return 1;

} // kreiranje i slanje callback objekta na server VehicleFactory_IAssemblyCallback_i* myVehicleFactory_IAssemblyCallback_i = new VehicleFactory_IAssemblyCallback_i(); PortableServer::ObjectId_var myVehicleFactory_IAssemblyCallback_iid = poa>activate_object(myVehicleFactory_IAssemblyCallback_i); dref->SetCallback(myVehicleFactory_IAssemblyCallback_i->_this()); while (true) { if (bNoBodiesLeft) { dref->PutPart(E_BODY, 5); bNoBodiesLeft = false; } if (bNoMotorsLeft) { dref->PutPart(E_MOTOR, 15); bNoMotorsLeft = false; } if (bNoWheelsLeft) { dref->PutPart(E_WHEEL, 3); bNoWheelsLeft = false; } Sleep(5000); } orb->run(); orb->destroy(); } catch(CORBA::TRANSIENT&) { cerr << "Caught system exception TRANSIENT -- unable to contact the " << "server." << endl; } catch(CORBA::SystemException& ex) { cerr << "Caught a CORBA::" << ex._name() << endl; } catch(CORBA::Exception& ex) { cerr << "Caught CORBA::Exception: " << ex._name() << endl; } catch(omniORB::fatalException& fe) { cerr << "Caught omniORB::fatalException:" << endl; cerr << " file: " << fe.file() << endl; cerr << " line: " << fe.line() << endl; cerr << " mesg: " << fe.errmsg() << endl; } return 0; }

Listing 11. Kod klijenta za b)

You might also like