Passaggio dei parametri Principali metodi di passaggio di parametri & procedure, SOAP & CORBA Java Remote Method Invocation Luca Colombi & Fabio Fazio
Passaggio dei parametri: principali metodi di passaggio Luca Colombi Passaggio dei parametri: principali metodi di passaggio Esistono 4 principali metodi per passare parametri: Call-by-value Call-by-reference Copy-restore Call-by-name
l-value ed r-value Due modi per riferirsi al significato-valore di una stessa espressione: Il suo l-value (left-value): si riferisce alla locazione rappresentata dall'espressione a sinistra del simbolo d’assegnazione: a[i] := 5+2 (l ≈ location) Il suo r-value (right-value): si riferisce al risultato dell’espressione a destra del simbolo d’assegnazione: (r ≈ result)
Parametri attuali e formali Ci può essere confusione tra parametro inteso come "parametro ricevuto dalla funzione chiamata" e parametro come "parametro passato dalla funzione chiamante". Avremo allora due modi di vedere un parametro: Parametro attuale: è il parametro che la funzione chiamante passa alla funzione chiamata, nel contesto della funzione chiamante. Parametro formale: è il parametro che la funzione chiamata riceve, nel contesto dell'esecuzione della funzione chiamata.
Call By Value E' usata per default in C ed in Pascal. I parametri attuali sono valutati, ed il loro r-value è passato alla procedura chiamata. Il Call-by-value può essere implementato come segue: Un parametro formale è trattato esattamente come un nome locale, così una locazione per il parametro passato viene riservata nel record d'attivazione della procedura chiamata. Per ogni parametro attuale, il chiamante ne valuta l'r-value e lo mette nella locazione del corrispondente parametro formale.
Call By Reference Quando i parametri sono passati per riferimento, il chiamante passa alla procedura chiamata un puntatore per ognuno dei parametri passati. Il Call-by-reference può essere implementato come segue: Se un parametro attuale è un nome o un'espressione con gia’ un l-value (locazione) proprio, allora il suo l-value è passato direttamente come parametro. Altrimenti, se il parametro attuale non ha un l-value, l'espressione è valutata e salvata in una nuova locazione, e l'indirizzo della nuova locazione è passato come parametro.
Emulare il Call By Reference con il Call By Value Una procedura chiamata per valore può cambiare lo stato della sua procedura chiamante attraverso variabili globali oppure attraverso puntatori esplicitamente passati come valori. Utilizzando il passaggio di valori per accedere direttamente a locazioni fuori della visibilità della funzione chiamata, si crea di fatto un passaggio per riferimento.
Copy-Restore Si tratta di una via di mezzo tra il Call-by-value e il Call-by-reference. E' usato in Ada e da alcune implementazioni del Fortran, mentre altre usano il Call-By-Reference. Può essere implementato come segue: Prima che il controllo passi alla procedura chiamata, gli r-value dei parametri attuali sono valutati. I valori già di tipo r-value vengono passati alla procedura chiamata come per il call-by-value. In più, i parametri attuali che hanno un l-value proprio vengono determinati prima della chiamata. Prima che il controllo ritorni, gli r-value dei parametri formali sono ricopiati negli l-value dei rispettivi parametri attuali, usando gli l-value calcolati prima della chiamata. I parametri che non avevano l-value al momento di essere passati non vengono ricopiati.
Esempio di caso in cui il programma si comporta diversamente a seconda che il passaggio sia Copy-Restore o Call By Reference: program copyout(input,output); //variabile globale var a : integer; procedure unsafe(var x, : integer); begin x := 2; //Call-By-Reference: sia 'x' che 'a' prendono r-value 2. //Copy-Restore: 'x' vale 2, 'a' verrà aggiornato al ritorno dalla procedura. a := 0; //Call-By-Reference: sia 'x' che 'a' prendono r-value 0. //Copy-Restore: 'a' vale 0 e viene aggiornato subito perchè è una variabile globale, 'x' resta 2. end; //Call-By-Reference: nessun cambiamento: 'a' resta con r-value 0. //Copy-Restore: 'a' prende l'ultimo valore di 'x', cioè 2. a := 1; unsafe(a); writeln(a); //Viene stampato a seconda che si usi il Copy-Restore: “2” o il Call-By-Reference: “0” end.
Call By Name Call-By-Name è usato per il passaggio parametri dell'Algol e per l’uso delle macro in C: La procedura è trattata come se ci fosse una macro, cioè il suo corpo viene sostituito alla corrispondente chiamata nella procedura chiamante, con i parametri attuali sostituiti letteralmente (per nome) dai parametri formali. Questa sostituzione è chiamata Macro-Expansion o In-Line-Expansion. I nomi locali della procedura chiamata vengono mantenuti distinti dai nomi della procedura chiamante, rinominando sistematicamente ogni nome locale con un nuovo nome distinto. I parametri attuali vengono chiusi tra parentesi se necessario per preservare la loro integrità.
Parametri di tipo procedura Luca Colombi Parametri di tipo procedura Alcuni linguaggi permettono di dichiarare variabili di tipo procedura o funzione. Un esempio: Oberon Pascal Oberon Modula Oberon è un linguaggio degli anni ’90, discendente del Pascal e orientato agli oggetti, che permette la dichiarazione e il passaggio di variabili di tipo funzione, nelle modalità Call-By-Value e Call-By-Reference.
Passaggio by-value e by-reference (variable) Passaggio di una funzione per valore: La variabile di tipo funzione passata può essere usata all’interno della funzione chiamata ma non subisce modifiche permanenti. Passaggio di una funzione per riferimento: La variabile di tipo funzione passata può essere usata all’interno della funzione chiamata, in più può ricevere l’assegnamento di un’altra funzione dello stesso tipo, che al ritorno dalla funzione chiamata rimane al posto di quella passata come parametro attuale. Il tipo della funzione sostituita deve coincidere con quello della funzione che la sostituisce, cioè i tipi, il numero e la posizione dei parametri delle due funzioni devono coincidere.
Java Remote Method Invocation Fabio Fazio
Java Remote Method Invocation RMI: goal Rendere trasparente l’invocazione remota di metodi su oggetti Java che risiedono su diverse Virtual machines Offrire un modello distribuito che preservi maggiormente la semantica degli oggetti Java Rendere il piu’ semplice possibile la scrittura di applicazioni distribuite
Java Remote Method Invocation Architettura RMI
Java Remote Method Invocation Architettura RMI Il sistema RMI e` costituito da tre livelli per supportare flessibilità nella comunicazione Ogni livello ha le sue interfacce di comunicazione con relativi protocolli stub (e skeleton) layer: canale di comunicazione tra clients e server remote reference layer: supporto di diversi protocolli di invocazione tipo Unicast e Multicast transport layer: supporta la comunicazione a basso livello, tipo TCP/IP
Java Remote Method Invocation RMI Simile all’invocazione di metodi locali I parametri dei metodi possono anche essere oggetti (grazie al meccanismo di Serializzazione) ma I Client interagiscono con interfacce di oggetti (stub) e non con la loro implementazione (che sta nella VM remota) I parametri vengono passati per copia, non per referenza (passaggio per referenza solo dentro a una VM)
Java Remote Method Invocation RMI in pratica L’oggetto sulla JVM Client desidera inviare un messaggio all’oggetto sulla JVM Server. L’oggetto sulla JVM Server terminata l’esecuzione restituisce l’oggetto come valore di ritorno oppure solleva un’eccezione Parametri
Passaggio dei parametri Java Remote Method Invocation Passaggio dei parametri Client Stub rete Skeleton Server invocazione metodo e invio parametri parametri originali serializzazione dei parametri (marshalling) marshalling trasmissione dati serializzati invio dati in rete unmarshalling decodifica dei parametri (unmarshalling) copia dei parametri originali ricezione dei parametri ed inizio elaborazione
Java Remote Method Invocation Ritorno dei risultati Client Stub rete Skeleton Server elaborazione dei parametri e calcolo del risultato risultato originale serializzazione del risultato (marshalling) marshalling trasmissione dati serializzati invio dati in rete decodifica del risultato (unmarshalling) unmarshalling copia del risultato originale ritorno del risultato della elaborazione
Java Remote Method Invocation Marshalling (1/3) Processo che trasforma un oggetto in memoria in una espressione serializzabile Si applica agli oggetti che vengono passati al metodo dell’oggetto remoto come parametro, ed al valore che il metodo ritorna Nel caso del passaggio di parametri il marshalling avviene nello Stub, nel ritorno dei risultati avviene nello Skeleton (Stub Server)
Java Remote Method Invocation Marshalling (2/3) I tipi semplici e gli oggetti meno complessi vengono serializzati direttamente Gli oggetti complessi richiedono invece un procedimento diverso si serializzano ricorsivamente i membri dell’oggetto si serializza l’oggetto Si crea così una copia dell’oggetto parametro su cui lavorerà il server remoto Lavorando su cloni non è possibile una vera e propria interazione “by reference”
Java Remote Method Invocation Marshalling (3/3) E’ necessario interagire su oggetti serializzabili, quindi non legati ad una rappresentazione propria del sistema operativo. Esempio la classe Java.awt.Image non è serializzabile, perché rimanda alla descrizione delle immagini propria dei singoli sistemi operativi E’ qundi necessario che gli oggetti parametro e l’oggetto risultato implementino l’interfaccia java.io.Serializable
Java Remote Method Invocation Unmarshalling E’ il procedimento opposto rispetto al Marshalling: trasforma rappresentazioni serializzate in oggetti “vivi”, in memoria I parametri serializzati dallo Stub in fase di richiamo dei metodi vengono decodificati dallo Skeleton, i valori di rirorno codificati dallo Skeleton vengono decodificati dallo Stub Valgono le stesse considerazioni sulla serializzazione degli oggetti fatte parlando del marshalling
Aspetti avanzati di Java RMI Java Remote Method Invocation Aspetti avanzati di Java RMI Modalità avanzate di passaggio parametri. passaggio by value. passaggio by remote reference. Remote callback. Oggetti server che implementano interfacce multiple.
Passaggio parametri by value Java Remote Method Invocation Passaggio parametri by value E’ la modalità comune. Viene passata all’oggetto server una copia speculare dell’oggetto presente nel client. Se la copia nel server viene modificata da una interazione indiretta, la copia sul client non ne rispecchierà le modifiche. Diventa possibile che le due copie perdano la congruenza reciproca. Ciononostante è un approccio valido nella stragrande maggioranza dei casi.
Passaggio parametri by remote reference (1/3) Java Remote Method Invocation Passaggio parametri by remote reference (1/3) A volte sarebbe comodo mantenere sempre la coerenza tra le copie dei parametri del server e del client. Occorre però un meccanismo che aggiorni automaticamente gli oggetti del client quando le rispettive copie presenti nel server subiscono una modifica. Occorre allora che la copia presente nel server notifichi alla rispettiva copia nel client ogni variazione, cioè un meccanismo RMI con client e server invertiti.
Passaggio parametri by remote reference (2/3) Java Remote Method Invocation Passaggio parametri by remote reference (2/3) Come implementare tale meccanismo? Occorre che il client passi al server non una semplice copia di un oggetto interno, bensì un riferimento ad un oggetto presente nel server, ovvero uno Stub di tale oggetto. Sorge il problema di come ricavare lo Stub di un oggetto del client. In quale modo il sistema riconosce un oggetto locale da un oggetto remoto? E’ un oggetto remoto un oggetto che estende l’interfaccia java.rmi.Remote.
Passaggio parametri by remote reference (3/3) Java Remote Method Invocation Passaggio parametri by remote reference (3/3) Quando il meccanismo di marshalling riconosce un oggetto che implementa l’interfaccia java.rmi.Remote, invece che inviare una copia dell’oggetto in questione ne invia uno Stub Per ottenere un passaggio valori by remote reference, occorre dichiarare come parametro formale un’interfaccia che deriva da java.rmi.Remote
Java Remote Method Invocation Remote Callback Allo stesso modo è possibile creare oggetti che implementino callback. Si crea un oggetto remoto che attenda un dato evento e richiami uno specifico metodo di un oggetto locale.
Server che implementano interfacce multiple Java Remote Method Invocation Server che implementano interfacce multiple È possibile che un oggetto server implementi più interfacce Si può così costruire un oggetto server che venga istanziato una volta sola e si comporti diversamente a seconda di come venga richiamato, ovvero che esporti metodi diversi a seconda di come vengano richiesti
SOAP: Simple Object Access Protocol Luca Colombi SOAP: Simple Object Access Protocol SOAP è progettato come “protocollo leggero per lo scambio di informazioni in ambiente distribuito”. In particolare uno dei suoi scopi più utili è come protocollo per chiamate di metodi remoti tra macchine diverse con sistemi diversi, fornendo la capacità di integrare sistemi che prima non erano facilmente in grado di comunicare e scambiarsi risorse. SOAP prende i parametri di una procedura nella forma nativa binaria e li trasporta al server remoto come informazioni XML, in genere tramite protocollo HTTP. Una volta a destinazione SOAP prende le informazioni XML e le riporta alla struttura binaria per l’elaborazione. Alcuni vantaggi particolari di SOAP sono: essere basato su testo (XML) non essere legato a soluzioni proprietarie I firewall spesso possono essere configurati facilmente per lasciar passare il protocollo HTTP.
Struttura di un pacchetto SOAP Http utilizza l’header per indirizzare il pacchetto, notificarne il contenuto (testo XML) e mantenere altre informazioni. L’Envelope SOAP funziona come wrapper per le informazioni passate, in questo caso i parametri delle procedure. L’Header SOAP è progettato per contenere meta-informazioni, per esempio un numero di account o l’algoritmo usato per crittografare le informazioni. Il Body contiene le informazioni che vogliamo trasportare. Pacchetto (http) Header (http) Soap XML Envelope Header Soap (opzionale) Body (il messaggio) Eventuali elementi personalizzati
Envelope SOAP: Chiamata tradotta in xml <?xml version =”1.0” encoding=”utf-8”?> <soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”> <soap:Header> <AccountNum xmlns=”http://www.companyurl.com/”> 11285-990 </AccountNum> </soap:Header> <soap:Body xmlns=”http://www.companyurl.com”> <GestisciOrdine> <Param1>informazioni su Param1..</Param1> </GestisciOrdine> </soap:Body> </soap:Envelope>
Envelope SOAP: Specifiche per la chiamata Le specifiche SOAP richiedono che il primo nodo figlio di Body abbia il nome della procedura remota: <soap:Body xmlns=”http://www.companyurl.com”> <GestisciOrdine> <Param1>informazioni su Param1..</Param1> … <ParamN>informazioni su ParamN..</ParamN> </GestisciOrdine> </soap:Body> Ogni discendente del nodo procedura è denominato in modo simile al parametro corrispondente.
Risposta tradotta in xml <?xml version =”1.0” encoding=”utf-8”?> <soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/envelope/” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=”http://www.w3.org/2001/XMLSchema”> <soap:Body xmlns=”http://www.companyurl.com”> <GestisciOrdineResponse> <GestisciOrdineResult> <Val>informazioni su Val</Val> </GestisciOrdineResult> </GestisciOrdineResponse> </soap:Body> </soap:Envelope>
CORBA: Common Object Request Broker Architecture Luca Colombi CORBA: Common Object Request Broker Architecture L’architettura CORBA è un ambiente standard a che permette l’interoperabilità tra oggetti in sistemi distribuiti eterogenei. I concetti base di CORBA sono: Object Services: Sono una collezione di servizi di sistema predefiniti. Uno dei principali Object Services è il servizio di naming. Naming Service: Il servizio di naming è il principale meccanismo che CORBA rende disponibile per l’identificazione degli oggetti. Object Request Broker (ORB): L’ORB è l’entità che riceve la richiesta dal client, identifica il percorso necessario per raggiungere l’oggetto target, provvede al suo inoltro e riporta l’eventuale risposta all’oggetto client. IDL: Interface Definition Language: serve a definire interfacce intese come insieme dei servizi disponibili. Object implementation: E l’insieme di codice e dati che effettivamente implementa un oggetto server.
ORB: chiamata di un metodo Il client esegue l'invocazione tramite un Object Reference, ottenibile ad esempio con il servizio di naming, che identifica univocamente l'interfaccia dell'oggetto server. Lavorare su un Object Reference ci permette di avere una sorta di “puntatore in remoto” e a livello di codice specificare le chiamate come locali. La chiamata può avvenire tramite uno stub o essere costruita dinamicamente tramite la DII (Dynamic Invocation Interface). L'ORB localizza l'oggetto server, trasmette i parametri e trasferisce il controllo al server tramite la server stub (o skeleton). CORBA ammette anche chiamate in modalita’ oneway: Sono chiamate remote che non hanno riscontro lato client. Client Object implementation Stub DII Skeleton (server stub) Object Adapter ORB
IDL: scopo Gli oggetti CORBA sono visti come “interfacce” specificate tramite l’IDL (Interface Definition Language). L’Interface Definition Language è un linguaggio dichiarativo usato per descrivere le operazioni di un componente software accessibili esternamente (interfacce). Nell’ambito di CORBA, IDL è usato per specificare i servizi offerti da ciascun oggetto server ad eventuali client.
IDL: gli stub Il mapping dell'IDL in un linguaggio descrive come si traducono la sintassi e semantica dell'IDL in quel particolare linguaggio. Dalla definizione di un'interfaccia in IDL è possibile derivare (tramite un compilatore che soddisfa il mapping prescritto da CORBA) gli stub lato client e server. Il processo di conversione delle strutture dati in messaggi è detto “marshaling”. Il processo di decodifica dei dati dal messaggio è detto “unmarshaling”. Gli stub realizzano le funzionalità di marshalling e unmarshalling dei paramentri e del valore di ritorno e rendono trasparente l’interazione dell'applicazione con l'ORB.
Parametri in IDL IDL supporta diversi tipi di dato semplici, tra cui Boolean, integer, string, sequences(array monodimensionali), eccezioni. Esempio: impiegato.idl interface impiegato { long numero(); }; interface registroImpiegati { impiegato trova(in long imp_num); registroImpiegati.trova(<long>) restituisce l’Object Reference di un oggetto di tipo impiegato. IDL permette di specificare le seguenti modalità: in: il parametro va solo dal client all’oggetto sul server out: il parametro viene usato come un ulteriore valore di ritorno, non viene passato dal client all’oggetto sul server ma fa solo il viaggio inverso Inout: il parametro è inizializzato dal client e mandato all’oggetto sul server, che però può rimandarlo indietro modificato.
The end