K.Subieta. SSR, Wykład 4, Folia 1 marzec 2009 Standardy w zakresie systemów rozproszonych i baz danych Kazimierz Subieta Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa Wykład 4: Wprowadzenie do OMG CORBA
K.Subieta. SSR, Wykład 4, Folia 2 marzec 2009 Zdefiniuj interfejsy serwera (klasy obiektów) używając IDL. Interfejsy w IDL informują klienta o obiektach, które są w zasięgu ORB, o ich atrybutach, o metodach, które wolno stosować, o parametrach i wyniku tych metod, oraz o wyjątkach, które mogą być powodowane przez metody. Wprowadź definicję interfejsu do repozytorium interfejsów, używając do tego celu specjalnego udogodnienia. Informację tę mogą wykorzystywać programy aplikacyjne np. dla celów wołań dynamicznych. Zastosuj prekompilator do definicji interfejsów w IDL. Typowy prekompilator CORBA wyprowadza co najmniej trzy rodzaje kodu wyjściowego: 1) pniaki klienta dla metod zdefiniowanych w IDL. Pniaki te są używane przez program klienta w celu statycznego dostępu do obiektów. 2) szkielety serwera, określające nagłówki metod (+ inne informacje), które mają być zaimplementowane po stronie serwera. 3) Specyficzną dla danego języka programowania definicję klasy (np w Java lub C++). 1 Wołanie statyczne: krok po kroku (1) 2 3 1) i 3) nie wymagają dalszych zabiegów, 2) musi być zapełnione kodem.
K.Subieta. SSR, Wykład 4, Folia 3 marzec 2009 Wołanie statyczne: krok po kroku (2) Dodaj kod po stronie serwera do szkieletu wyprodukowanego przez wyrażenie IDL. Kod ten implementuje metody zdefiniowane w wyrażeniu IDL. Skompiluj ten kod, używając w tym celu normalnego kompilatora wybranego języka programowania. Zarejestruj obiekty serwera w Repozytorium Implementacji. ORB używa tej informacji celem zlokalizowania aktywnych obiektów lub celem wykonania ich aktywacji. Rejestracja obiektów wymaga napisania programu o dość standardowej budowie. Utwórz instancje obiektów na serwerze. W czasie startu aplikacji, Adapter Obiektów znajdujący się na serwerze może tworzyć obiekty, które będą obsługiwać odległe wołania metod ze strony klienta. CORBA definiuje specjalne strategie Adaptera Obiektów, które są używane do tworzenia i zarządzania tego rodzaju obiektami
K.Subieta. SSR, Wykład 4, Folia 4 marzec 2009 Wołanie statyczne: krok po kroku (3) Zaimplementuj kod aplikacji klienta, która będzie używać obiektów serwera wcześniej zdefiniowanych, zaimplementowanych i utworzonych. Skompiluj ten kod używając normalnego kompilatora wybranego języka programowania. Nie zapomnij o dołączeniu podczas kompilacji pliku z pieńkiem klienta utworzonym z wyrażenia IDL. 8 9 Podana wyżej procedura jest typowa, ale może mieć wiele odmian. Niektóre kroki mogą być pominięte, np. nie ma potrzeby definiowania wyrażenia IDL, jeżeli zostało ono wcześniej wprowadzone do Interface Repository i został już utworzony wcześniej pieniek klienta.
K.Subieta. SSR, Wykład 4, Folia 5 marzec 2009 Nasz pierwszy program w CORBA: Counter Program jest minimalistyczną aplikacją klient-serwer. Jest to działająca aplikacja w Java pod VisiBrokerem. Zakładamy, ze po stronie serwera będzie znajdować się maciupeńki obiekt zawierający licznik (counter). Dostęp do tego obiektu będzie określony poprzez atrybut sum (suma przechowywana w liczniku) oraz przez metodę increment (zwiększ sum o 1). Metoda ta będzie zwracać wartość licznika do klienta. Co będzie robić nasza aplikacja po stronie klienta? 1) Ustawia licznik na zero; 2) Wywołuje metodę increment 1000 razy; 3) Podaje końcową sumę w liczniku; 4) Drukuje odcinek czasu, w którym działał program. 5) Powinien reagować na wyjątki.
K.Subieta. SSR, Wykład 4, Folia 6 marzec 2009 Counter: wyrażenie IDL // count.idl module Counter { interface Count { attribute long sum; long increment(); }; prompt>idl2java count.idl -no_comments -no_tie Wywołanie prekompilatora: program VisiBrokera nie generuj dodatkowych klas dla delegacji
K.Subieta. SSR, Wykład 4, Folia 7 marzec 2009 Counter: klasy i interfejsy Java generowane przez prekompilator count.idl Kompilator idl2java Kompilator idl2java CORBA IDL Prekompilator klasa interfejsklasa _st_CountCountHelper CountHolder Count _CountImplBase_example_Count Strona klienta Java Strona serwera Java Counter { {
K.Subieta. SSR, Wykład 4, Folia 8 marzec 2009 Jakie to są pliki? _st_count: CountHelper CountHolder _CountImplBase Count _example_Count Pieniek klienta, który ma być skompilowany łącznie z jego aplikacją. Zawiera funkcje szeregujące argumenty metod. Jest to klasa Java zapewniająca użyteczne funkcje pomocy dla klientów. (Nie jest na razie dla nas interesująca.) Jest to klasa Java umożliwiająca traktowanie obiektów typu Count jako parametrów metod. (Nie jest na razie dla nas interesująca.) Klasa Java zawierająca szkielet implementacji metod od strony serwera. Zajmuje się rozszeregowaniem argumentów metod. Interfejs Java automatycznie generowany z wyrażenia IDL. Musimy przewidzieć kod, który zaimplementuje ten interfejs. Przykładowa klasa, ustalająca ramowe założenia metod, które musimy wypełnić kodem implementacji.
K.Subieta. SSR, Wykład 4, Folia 9 marzec 2009 Counter: Pieniek klienta generowany automatycznie package Counter; public class _st_Count extends org.omg.CORBA.portable.ObjectImpl implements Counter.Count { public java.lang.String[] _ids() { return __ids; } private static java.lang.String[] __ids = { "IDL:Counter/Count:1.0" }; public int increment() { try { org.omg.CORBA.portable.OutputStream _output = this._request("increment", true); org.omg.CORBA.portable.InputStream _input = this._invoke(_output, null); int _result; _result = _input.read_long(); return _result; } catch(org.omg.CORBA.TRANSIENT _exception) { return increment(); } public void sum(int sum) { try { org.omg.CORBA.portable.OutputStream _output = this._request("_set_sum", true); _output.write_long(sum); org.omg.CORBA.portable.InputStream _input = this._invoke(_output, null); } catch(org.omg.CORBA.TRANSIENT _exception) { sum( sum ); } public int sum() { try { org.omg.CORBA.portable.OutputStream _output = this._request("_get_sum", true); org.omg.CORBA.portable.InputStream _input = this._invoke(_output, null); int _result; _result = _input.read_long(); return _result; } catch(org.omg.CORBA.TRANSIENT _exception) { return sum(); } Jest to wewnętrzna implementacja pieńka klienta dla interfejsu Count. Zajmuje się głównie szeregowaniem argumentów wołań do serwera. Nie musimy interesować się tym kodem. Wszystko, co należy z nim zrobić, to skompilować i zlinkować go łącznie z aplikacją klienta. _st_count:
K.Subieta. SSR, Wykład 4, Folia 10 marzec 2009 Counter: Szkielet serwera generowany automatycznie package Counter; abstract public class _CountImplBase extends org.omg.CORBA.portable.Skeleton implements Counter.Count { protected _CountImplBase(java.lang.String name) { super(name); } protected _CountImplBase() { } public java.lang.String[] _ids() { return __ids; } private static java.lang.String[] __ids = { "IDL:Counter/Count:1.0" }; public org.omg.CORBA.portable.MethodPointer[] _methods() { org.omg.CORBA.portable.MethodPointer[] methods = { new org.omg.CORBA.portable.MethodPointer("increment", 0, 0), new org.omg.CORBA.portable.MethodPointer("_set_sum", 0, 1), new org.omg.CORBA.portable.MethodPointer("_get_sum", 0, 2), }; return methods; } public boolean _execute(org.omg.CORBA.portable.MethodPointer method, org.omg.CORBA.portable.InputStream input, org.omg.CORBA.portable.OutputStream output) { switch(method.interface_id) { case 0: { return Counter._CountImplBase._execute(this, method.method_id, input, output); } throw new org.omg.CORBA.MARSHAL(); } public static boolean _execute(Counter.Count _self, int _method_id, org.omg.CORBA.portable.InputStream _input, org.omg.CORBA.portable.OutputStream _output) { switch(_method_id) { case 0: { int _result = _self.increment(); _output.write_long(_result); return false; } case 1: { int sum; sum = _input.read_long(); _self.sum(sum); return false; } case 2: { int _result = _self.sum(); _output.write_long(_result); return false; } throw new org.omg.CORBA.MARSHAL(); } _CountImplBase Jest to wewnętrzna implementacja szkieletu serwera dla interfejsu Count. Zajmuje się głównie rozszeregowaniem argumentów wołań do serwera. Nie musimy interesować się tym kodem. Wszystko, co należy z nim zrobić, to skompilować i zlinkować go łącznie z programem serwera.
K.Subieta. SSR, Wykład 4, Folia 11 marzec 2009 Counter: interfejs w Java generowany z IDL package Counter; public interface Count extends org.omg.CORBA.Object { public void sum(int sum); public int sum(); public int increment(); } Musimy napisać kod, który zaimplementuje ten interfejs. Count
K.Subieta. SSR, Wykład 4, Folia 12 marzec 2009 Counter: przykład klasy implementującej interfejs w IDL package Counter; public class _example_Count extends Counter._CountImplBase { public _example_Count(java.lang.String name) { super(name); } public _example_Count() { super(); } public int increment() { // implement operation... return 0; } public void sum(int sum) { // implement attribute writer... } public int sum() { // implement attribute reader... return 0; } _example_Count Określany jako example servant - usługodawca
K.Subieta. SSR, Wykład 4, Folia 13 marzec 2009 Counter: Główny program serwera // CountServer.java: The Count Server main program class CountServer { static public void main(String[] args) { try { // Initialize the ORB org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); // Initialize the BOA org.omg.CORBA.BOA boa = orb.BOA_init(); // Create the Count object CountImpl count = new CountImpl("My Count"); // Export to the ORB the newly created object boa.obj_is_ready(count); // Ready to service requests boa.impl_is_ready(); } catch(org.omg.CORBA.SystemException e) { System.err.println(e); } Musimy napisać ten program wg pewnego wzorca. Inicjalizuje ORB, inicjalizuje BOA, tworzy obiekt count po stronie serwera i rejestruje ten obiekt w Repozytorium Interfejsów.
K.Subieta. SSR, Wykład 4, Folia 14 marzec 2009 Counter: Szkielet wypełniony implementacją // CountImpl.java: The Count Implementation class CountImpl extends Counter._CountImplBase { private int sum; // Constructors CountImpl(String name) { super(name); System.out.println ("Count Object Created"); sum = 0; } // get sum public int sum() { return sum; } // set sum public void sum(int val) { sum = val; } // increment method public int increment() { sum++; return sum; } Klasa _CountImplBase jest rozszerzona poprzez klasę CountImpl, stworzoną z przykładu _example_Count. Razem klasy _CountImplBase i CountImpl tworzą implementację obiektu po stronie serwera.
K.Subieta. SSR, Wykład 4, Folia 15 marzec 2009 Counter: program klienta (nasza aplikacja) // CountClient.java Static Client, VisiBroker for Java class CountClient { public static void main(String args[]) { try { // Initialize the ORB System.out.println("Initializing the ORB"); org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); // Bind to the Count Object System.out.println("Binding to Count Object"); Counter.Count counter = Counter.CountHelper.bind(orb, "My Count"); // Set sum to initial value of 0 System.out.println("Setting sum to 0"); counter.sum((int)0); // Calculate Start time long startTime = System.currentTimeMillis(); // Increment 1000 times System.out.println("Incrementing"); for (int i = 0 ; i < 1000 ; i++ ) { counter.increment(); } // Calculate stop time; print out statistics long stopTime = System.currentTimeMillis(); System.out.println("Avg Ping = " + ((stopTime - startTime)/1000f) + " msecs"); System.out.println("Sum = " + counter.sum()); } catch(org.omg.CORBA.SystemException e) { System.err.println("System Exception"); System.err.println(e); }
K.Subieta. SSR, Wykład 4, Folia 16 marzec 2009 Wołanie dynamiczne: krok po kroku (1) 1 Spytaj obiekt o jego definicję interfejsu, wołajac metodę get_interface. Otrzymasz InterfaceDef obiekt, który opisuje twój obiekt w Repozytorium Interfejsów. Poszukaj metody, która cię interesuje, poprzez wywołanie metody lookup_name na otrzymanym obiekcie InterfaceDef. Otrzymasz obiekt typu OperationDef. Odzyskaj opis interesującej cie metody, poprzez wywołanie metody describe na obiekcie OperationDef. Utwórz pustą listę NVList, poprzez metodę create_list. Lista ta będzie przeznaczona na wartości argumentów twojej metody. Zapełń NVlist wartościami argumentów, używając metod add_item i add_value
K.Subieta. SSR, Wykład 4, Folia 17 marzec 2009 Wołanie dynamiczne: krok po kroku (2) 6 Utwórz obiekt Request twojego zlecenia, poprzez wywołanie metody create_request. Trzeba zakumonikować dla tej metody: 1) nazwę interesującej cie metody, 2) NVlist, 3) NamedValue w którym będzie zwrócony rezultat metody. Wywołaj odległą operację, poprzez wywołanie invoke na obiekcie Request. Jest to wywołanie synchroniczne. Rezultat wywołanie pojawi się w obiekcie Request. Wykorzystaj resultat i następnie zwolnij obiekt Request, który dalej jest zbędny. Zwolnij NVlist, poprzez wywołanie zlecenia free, które zwalnia miejsce związane z NVlist Jak widać, zlecenia dynamiczne są dość kłopotliwe. Niektóre czynności są wspomagane przez ORB.
K.Subieta. SSR, Wykład 4, Folia 18 marzec 2009 Podstawowy cel: współdziałanie pomiędzy ORB-ami wyprodukowanymi przez różne firmy. Wersje poprzedzające 2.0 nie zapewniały tej własności ze względu na brak standardu formatu danych i protokółów dla komunikacji pomiędzy ORB-ami. Bezpośrednie współdziałanie (direct interoperability): jest możliwe gdy ORB-y są umieszczone w tej samej dziedzinie: rozumieją te same referencje do obiektów, ten sam system typów w OMG IDL i te same środki bezpieczeństwa. Bezpośrednie współdziałanie (direct interoperability): jest możliwe gdy ORB-y są umieszczone w tej samej dziedzinie: rozumieją te same referencje do obiektów, ten sam system typów w OMG IDL i te same środki bezpieczeństwa. Współdziałanie bazujące na mostach (bridge-based interoperability): jest potrzebne do komunikacji ORB-ów z różnych dziedzin. Mają one za zadanie odwzorować informację specyficzną dla jednego ORB-u w informację właściwa dla innego. Współdziałanie bazujące na mostach (bridge-based interoperability): jest potrzebne do komunikacji ORB-ów z różnych dziedzin. Mają one za zadanie odwzorować informację specyficzną dla jednego ORB-u w informację właściwa dla innego. General Inter-ORB Protocol (GIOP) - specyfikuje składnie transferowanej informacji, format komunikatów. Jest prosty i łatwy w implementacji. Internet Inter-ORB Protocol (IIOP) - specyfikuje GIOP poprzez transport TCP/IP. Environment-Specific Inter-ORB Protocols (ESIOP), np. bazujący na OSF DCE. Protokoły pomiędzy ORB-ami Inter-ORB Protocols
K.Subieta. SSR, Wykład 4, Folia 19 marzec 2009 Rodzaje usług obiektowych (1) Usługa w zakresie cyklu życiowego (Life Cycle Service). Definiuje operacje tworzenia, kopiowania, przemieszczania, i usuwania komponentów (obiektów) będących pod kontrolą danej aplikacji zintegrowanej poprzez standard CORBA. Usługa w zakresie trwałości (Persistence Service). Definiuje interfejs do składowania komponentów (obiektów) na trwałych nośnikach, włączając w to obiektowe bazy danych, relacyjne bazy danych i zwykłe pliki. Usługa w zakresie nazywania (Naming Service). Pozwala nadać komponentom (obiektom) nazwy (o hierarchicznej budowie) oraz odzyskać identyfikatory komponentów (obiektów) na podstawie ich nazw. Usługa pozwala przywiązać komponenty (obiekty) do istniejącego nazewnictwa katalogów systemów operacyjnych lub kontekstów nazwowych wg różnorodnych systemów: ISO X.500, OSF DCE, Sun NIS+, Novell NDS, Internet LDAP. Usługa w zakresie zdarzeń (Event Service). Pozwala określić, czy dane komponenty mają reagować (nie reagować) na określone zdarzenia. Object Services
K.Subieta. SSR, Wykład 4, Folia 20 marzec 2009 Rodzaje usług obiektowych (2) Usługa w zakresie współbieżności (Concurrency Control Service). Pozwala zakładać/zdejmować zamki na obiekty (lub inne byty) celem przeciwdziałania kolizjom transakcji lub wątków. Usługa w zakresie transakcji (Transaction Service). Przewiduje koordynację transakcji opartą na dwufazowym potwierdzeniu (2PC) dla prostych i zagnieżdżonych transakcji. Usługa w zakresie związków (Relationship Service). Przewiduje dynamiczne tworzenie/usuwanie powiązań (związków, asocjacji) pomiędzy obiektami, wymuszanie więzów referencyjnych, oraz nawigację od obiektów do obiektów wg zdefiniowanych dla nich związków. Usługa w zakresie udostępniania obiektów na zewnątrz (Externalization Service). Przewiduje wstawianie i odczytywanie danych do/z komponentów (obiektów). Object Services
K.Subieta. SSR, Wykład 4, Folia 21 marzec 2009 Rodzaje usług obiektowych (3) Usługa w zakresie zapytań (Query Service). Przewiduje dostęp do obiektów poprzez różnorodne języki zapytań, wśród nich SQL-92, nowo powstający standard SQL3, oraz obiektowy język zapytań (standardu ODMG) OQL. Usługa w zakresie licencji (Licensing Service). Usługa pozwala na pomiary użycia komponentów (obiektów) oraz wyliczenie opłat za użycie w ramach sesji, węzła sieci, itd. Usługa w zakresie dodatkowych własności obiektów (Properties Service). Pozwala dynamicznie związać z obiektami dowolne nazwane własności (atrybuty), np. datę utworzenia, datę ostatniej modyfikacji, nazwisko modyfikującego, itd. Usługa w zakresie czasu (Time Services). Przewiduje interfejsy do synchronizowania czasu w środowisku rozproszonym. Pozwala również definiować zdarzenia wyzwalane przez upływ czasu. Object Services
K.Subieta. SSR, Wykład 4, Folia 22 marzec 2009 Rodzaje usług obiektowych (4) Usługa w zakresie ochrony (Security Service). Zapewnia możliwości pełnej ochrony rozproszonych obiektów. Wspomaga autoryzację, sterowanie dostępem, tajność i przeciwdziałanie unikaniu zapłaty (non-repudiation). Zarządza także oddelegowywaniem uwierzytelnień (credentials). Usługa handlowa (Trader Service). Przewiduje odzyskiwanie informacji o obiektach na podstawie ich własności, publikować informacje o serwisach dostarczanych przez obiekty, itd. Usługa w zakresie kolekcji (Collection Service). Przewiduje interfejsy do tworzenia najczęściej spotykanych kolekcji (zbiorów, wielozbiorów, sekwencji, itd.) i manipulacji tymi kolekcjami. Zestaw usług obiektowych jest rozszerzany w standardzie CORBA 3.0. Object Services
K.Subieta. SSR, Wykład 4, Folia 23 marzec 2009 Oddzielenie interfejsu i implementacji Referencje do obiektów podlegają kontroli typu poprzez interfejsy Klienci zależą od interfejsów, a nie od implementacji Stosowane jest wielo-dziedziczenie interfejsów Stosowana jest metoda tworzenia podtypów dla rozszerzenia, ewolucji i specjalizacji funkcjonalności Prostota, elastyczność, generyczność serwisów Umożliwienie lokalnych i odległych implementacji obiektów Oddzielenie interfejsu i implementacji Referencje do obiektów podlegają kontroli typu poprzez interfejsy Klienci zależą od interfejsów, a nie od implementacji Stosowane jest wielo-dziedziczenie interfejsów Stosowana jest metoda tworzenia podtypów dla rozszerzenia, ewolucji i specjalizacji funkcjonalności Prostota, elastyczność, generyczność serwisów Umożliwienie lokalnych i odległych implementacji obiektów Interfejsy wołań zwrotnych (Callback Interfaces) - serwer woła wykonanie usług ze strony klienta - np. przekazywanie danych asynchronicznie do klienta Interfejsy wołań zwrotnych (Callback Interfaces) - serwer woła wykonanie usług ze strony klienta - np. przekazywanie danych asynchronicznie do klienta Brak globalnych przestrzeni identyfikatorów - zakres identyfikatorów jest zawsze ograniczony do pewnego kontekstu. Brak globalnych przestrzeni identyfikatorów - zakres identyfikatorów jest zawsze ograniczony do pewnego kontekstu. Zasady projektowania usług obiektowych