Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma...

43
Chamada Remota de Procedimento (RPC)

Transcript of Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma...

Page 1: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

Chamada Remota de Procedimento (RPC)

Page 2: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

padrão cliente-servidor

A (cliente) B (servidor)

send (B, pedido)receive(B, &resp)

receive (A, …)processa pedidosend(A, …)

• repetição de padrão de comunicação• encapsulação em abstração de mais alto nível

– transparência

Page 3: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

chamada remota

A (cliente) B (servidor)

send (B, pedido)receive(B, &resp)

receive (A, …)processa pedidosend(A, …)

• transformação em chamada de procedimento– transparência para comunicação e suporte a passagem de parâmetros

Page 4: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

chamadas locais

main

proc1

proc5

proc2 proc3 proc4

proc6 proc8proc7

• programa convencional organizado e entendido emcomo uma sequência de chamadas a procedimentos

Page 5: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

chamada remota

main

proc1

proc5

proc2 proc3 proc4

proc6 proc8proc7

Computador 1 Computador 2

• protocolo permite chamada de procedimento remoto• chamada remota pode ficar mais ou menos• ênfase em estruturação do programa

– bastante associado ao modelo cliente-servidor

Page 6: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

chamadas remotas

• possibilidade de estruturas mais complexas– mais comum em sistemas de objetos distribuídos

main

proc1

proc5

proc2 proc3 proc4

proc6proc8

proc7

Page 7: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

RPC: modelo de execução

• processo cliente permanece bloqueadodurante execução de chamada remota

A (cliente) B (servidor)

resp = foo(a1, a2, …)

function foo (arg1, arg2,…) … return respostaend

Page 8: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

• stubs são responsáveis por intermediar acomunicação entre quem faz a chamada(caller) e quem é chamado (callee)

RPC: modelo de execução

cliente

stub cliente

servidor

stub servidor

Page 9: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

RPC - papel dos stubs

processo chamador processo chamado

cham local

stub cliente stub servidor

runtime RPCruntime RPC

Page 10: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

camadas envolvidas

• supondo uso de TCP– protocolo sobre TCP– conversão de dados– conversão de chamada remota em protocolo TCP

ferramenta

stubs cli e srv

prg cliente

protocolo

tcp

conversão entre formatos de repres.

Page 11: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

ferramentas/ geração de stubs

• linguagens que incorporam conceito de RPC– compilador gera diferentes partes do programa e stubs

• bibliotecas + ferramentas– possivelmente com interoperabilidade entre linguagens

servidor

stub servidor

cliente

stub cliente

descrição interface

stub servidor

stub clientegerador de stubs

compilador

programa fonte

Page 12: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

conversão de dados

• marshalling/unmarshalling– empacotamento e desempacotamento

• problemas– representações diferentes para inteiros– alinhamento de dados– estruturas com ponteiros

Page 13: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

soluções

• representação em XML (web services)

• XDR (external data representation)

• rotinas de conversão escritas pelo programador

Page 14: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

RPC

• Birrell e Nelson: 1984– PARC– implementação em linguagens como CCLU

• Sun RPC• objetos distribuídos:

– CORBA, RMI, J2EE, …• SOAP

Page 15: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

Um exemplo de RPC: Sun-RPC

• Sistema originalmente criado para máquinas Sun.– oferecido atualmente em diversos sistemas operacionais!

• A arquitetura definida inclui:– uma linguagem para definição das interfaces (cabeçalhos

de procedimentos, etc);– a ferramenta RPCGEN, que gera os stubs cliente e servidor

automaticamente;– uma biblioteca RPC, que pode ser usada diretamente na

construção de programas que não usem o RPCGEN;– o protocolo de comunicação entre os stubs.

• Pode utilizar TCP ou UDP

Page 16: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

Sun-RPC - Tradução de dados

• tradução entre formatos de dados: utilizaçãode uma representação padrão, XDR(eXternal Data Representation Standard).

• conversão é especificada para um conjuntopré-definido de tipos de dados.

formatoorigem

formatopadrão

formatodestino

Page 17: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

rpcgen - funcionamento

prog.x rpcgen bibliotecaRPC

cc

ccrprog.c

prog_proc.c

prog_clnt.c

prog.h

prog_svc.c

rprog

prog_svcprocedimentos servidores

cliente

especificação RPC

stub servidor

stub cliente

programa servidor

programa cliente

Page 18: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

rpcgen

• Exemplo de arquivo de especificação:

/* date.x especificação de serviços remotos de data e hora */

program DATE_PROG{ version DATE_VERS{ long BIN_DATE(void) = 1; string STR_DATE(long) = 2; } = 1;} = 0x31234567;

Page 19: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

passo 1: projetar uma aplicaçao convencional

main

proxima insere remove buscainicializar

Page 20: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

passo 2: dividir o programa em duas partes

insere

remove

busca

inicializarmain

proxima

Bancode

Dados

Chamadas aProcedimentos Remotos

Cliente Programa Remoto

Page 21: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

passo 3: criar uma especificação rpcgen

/* rbd.x especificação rpc para um programa de banco de dados que oferece os procedimentos INSERE, REMOVE e BUSCA*/

struct example { /* estrutura não usada, declarada para ilustrar como rpcgen */int exfield1; /* constrói rotinas XDR para converter estruturas */char exfield2;

};

program RBDPROG{ /* nome do programa remoto */ version RDBVERS{ /* declaração da versão */ int INICIALIZAR(void) = 1; /* primeiro procedimento deste programa */ int INSERE(string) = 2; /* segundo procedimento deste programa */

int REMOVE(string) = 3; /* terceiro procedimento deste programa */int BUSCA(string) = 4; /* quarto procedimento deste programa */

} = 1; /* definição da versão do programa */} = 0x30090949; /* número do programa remoto (deve ser único) */

Page 22: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

passo 4: rodar o rpcgen

• rpcgen rbd.x

rpcgen

rdb_clnt.c

rdb.h

rdb_svc.c

rdb_xdr.c

Page 23: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

rpcgenarquivo .h

/* rbd.h */

struct example {int exfield1;char exfield2;

};

typedef sruct example example;bool_t xdr_example();

#define RBDPROG (u_long) 0x30090949)#define RDBVERS ((u_long) 1)#define INICIALIZAR ((u_long) 1)extern int *inicializar_1();#define INSERE ((u_long) 2)extern int *insere_1();#define REMOVE ((u_long) 3)extern int *remove_1();#define BUSCA ((u_long) 4)extern int *busca_1();

Page 24: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

rpcgenarquivo de conversão XDR

/* rbd_xdr.c */#include <rpc/rpc.h>#include “rbd.h”

bool_txdr_example(xdrs, objp)

XDR *xdrs;example *objp;

{if (!xdr_int(xdrs, &objp->exfield1)) {

return(FALSE);}if (!xdr_char(xdrs, &objp->exfield2) {

return(FALSE);}return(TRUE);

}

Page 25: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

rpcgenstub do cliente

/* rbd_clnt.c */#include <rpc/rpc.h>#include “rbd.h”

int * inicializar_1(argp, clnt) void *argp; CLIENT *clnt;{ static int res;

bzero((char *)&res, sizeof(res)); if (clnt_call(clnt, INICIALIZAR, xdr_void, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS)

return (NULL); return (&res);}

int *insere_1(argp, clnt) char **argp; CLIENT *clnt;{ static int res; bzero((char *)&res, sizeof(res)); if (clnt_call(clnt, INSERE, xdr_wrapstring, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS)

return (NULL); return (&res);}

int * remove_1(argp, clnt) char **argp; CLIENT *clnt;{ static int res;

bzero((char *)&res, sizeof(res)); if (clnt_call(clnt, REMOVE, xdr_wrapstring, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS)

return (NULL); return (&res);}

int *busca_1(argp, clnt) char **argp; CLIENT *clnt;{ static int res; bzero((char *)&res, sizeof(res)); if (clnt_call(clnt, BUSCA, xdr_wrapstring, argp, xdr_int, &res, TIMEOUT) != RPC_SUCCESS)

return (NULL); return (&res);}

Page 26: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

rpcgenstub do servidor

/* rbd_svc.c */#include <rpc/rpc.h>#include “rbd.h”

static void rbdprog_1();

main(){ SVCXPRT *transp; (void)pmap_unset(RBDPROG, RBDVERS);

transp = svcudp_create(RPC_ANYSOCK); if (transp == NULL) { (void) fprintf(“Não pode criar serviço udp\n”); exit(1); } if (!svc_register(transp, RBCPROG, RBDVERS, rbdprog_1, IPPROTO_UDP)) { (void) fprintf(“Não pode registrar tal prog.\n”); exit(1); } transp = svctcp_create(RPC_ANYSOCK, 0, 0); if (transp == NULL) { (void) fprintf(“Não pode criar serviço TCP\n”); exit(1); } if (!svc_register(transp, RBCPROG, RBDVERS, rbdprog_1, IPPROTO_TCP)) { (void) fprintf(“Não pode registrar tal prog.\n”); exit(1); }

svc_run(); (void)fprintf(“SVC_RUn retornado \n”); exit(1);}

static void rbdprog_1(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp;{ union {

char *insere_1_arg;char *remove_1_arg; char *busca_1_arg;

} argument; char *result; bool_t (*xdr_argument) (), (*xdr_result)(); char *(*local)();

switch (rqstp->rq_proc) { case NULLPROC: ( void)svc_sendreply(transp, xdr_void,(char *) NULL); return; case INICIALIZAR: xdr_argument = xdr_void; xdr_result = xdr_int; local = (char *(*)())inicializar_1; break; case INSERE: xdr_argument = xdr_wrapstring; xdr_result = xdr_int; local = (char *(*)()) insere_1; break;

Page 27: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

rpcgencontinuação stub do servidor

case REMOVE: xdr_argument = xdr_wrapstring; xdr_result = xdr_int; local = (char *(*)())remove_1; break; case BUSCA: xdr_argument = xdr_wrapstring; xdr_result = xdr_int; local = (char *(*)()) busca_1; break; default: svcerr_noproc(transp); return; } bzero((char*)&argument, sizeof(argument)); if (!svc_getargs(transp, xdr_argument, &argument)) { svcerr_decode(transp); return; } result = (*local)(&argument, rqstp); if (result != NULL && !svc_sendreply(transp, xdr_result, result )) {

svcerr_systemerr(transp); } if (!svc_freeargs(transp, xdr_argument, &argument)) { (void)fprintf(“Problema nos argumentos\n”); exit(1); }}

Page 28: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

passo 5: escrever procedimentos de interface com ostub

/* rbd_cif.c - inicializar, insere, remove, busca */#include <rpc/rpc.h>#include “rbd.h”extern CLIENT *handle; /* handle para procedimento

remoto */

int inicializar(){

return *inicializar_1(handle);}int insere(item)char *item;{

char **arg;arg = &item;return *insere_1(arg, handle);

}

• Rotinas de Interface do Clienteint remove(item)char *item;{

char **arg;arg = &item;return *remove_1(arg, handle);

}int busca(item)char *item;{

char **arg;arg = &item;return *busca_1(arg, handle);

}

Page 29: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

rotinas de interface do servidor

/* rbd_sif.c - inicializar_1, insere_1, remove_1, busca_1 */#include <rpc/rpc.h>#include “rbd.h”static int retcode;

int *inicializar_1(){

retcode = inicializar();return &retcode;

}int *insere_1(i)char **i;{

retcode = insere(*i);return &retcode;

}

int *remove_1(i)char **i;{ retcode = remove(*i);

return &retcode;}int *busca_1(i)char **i;{

retcode = busca(*i);return &retcode;

}

Page 30: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

passo 6: compilar e linkar o programa cliente

• cc -c rbd_cif.c rbd_cif.o

• cc -c rbd.c rdb.o

• cc -o rbd rbd.o rbd_clnt.o rbd_xdr.o rbd_cif.o

Page 31: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

passo 7: compilar e linkar o programa servidor

• cc -c rbd_sif.c rbd_sif.o

• cc -c rbd_srp.c rdb_srp.o

• cc -o rbddaemon rbd_svc.o rbd_xdr.o rbd_sif.orbd_srp.o

Page 32: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

/* rbd_srp.c - inicializar, insere, remove, busca*/#include <rpc/rpc.h>#include “rbd.h”

/* Procedimentos remotos do servidor e dados globais */

char bd[BDSIZE][MAXWORD+1] /* armazena o dicionário de palavras */int npalavras = 0; /* número de palavras no dicionário */

int inicializar(){

npalavras = 0;return 1;

}

int insere(palavra)char *palavra;{

strcpy(bd[npalavras], palavra);npalavras++;return npalavras;

}

int remove(palavra)char *palavra;{

int i;for (i=0; i<npalavras; i++)

if (strcmp(palavra, bd[i]) == 0) { npalavras--; strcpy(bd[i], bd[npalavras]); return 1;}

return 0;}

int busca(palavra)char *palavra;{

int i;for (i=0; i<npalavras; i++)

if (strcmp(palavra, bd[i]) == 0 ) return 1;

return 0;}

Programa Servidor

Page 33: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

semântica de chamadas

• pelo menos uma vez• no máximo uma vez• exatamente uma vez

• relação com protocolo subjacente

Page 34: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

binding

• amarração entre cliente e servidor reedita problemade localização de destinatário– solução portmapper no Sun RPC

• em geral: chamada a servidor que detém:– nome– localização (IP, porta)– estado

• e se…– nenhum servidor for localizado– vários servidores forem localizados

Page 35: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

dinamismo…

• modelo apresentado exige conhecimento sobreinterfaces antes da geração do programa cliente– geração estática de stubs– suficiente para maior parte das situações

• adaptação dinâmica– servidores com diferentes otimizações

• cache– otimização dependendo do estilo de uso do cliente

• chamada dentro de loop– descoberta dinâmica de servidores

• relação com serviços de binding mais complexos

Page 36: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

críticas

• sincronismo• dificuldades de modelar outras formas de

iteração, como pipes ou multicast• dificuldades de tratamento de falhas

Page 37: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

sincronismo

• processo que faz a chamada permanecebloqueado– falta de interatividade local– desperdício de uso da CPU

• processamento• outras operações de comunicação

Page 38: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

RPC e multithreading

• combinação de RPC commultithreading– sobreposição de computação

e comunicação– disparo de várias chamadas

• trocas de contextopreemptivas– custo– necessidade de sincronização

A1 BA2C

Page 39: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

RPC assíncrona

• controle retorna imediatamente

function funcb(v) globalVal = vendobtemNovoVal(args, funcb);

• em alguns casos, função de callback podeser chamada qdo chamada se completa

registravalor(novoval);

Page 40: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

exemplo luarpc

function request(peers) local acc, repl = 0, 0 local expected = table.getn(peers) function avrg (val) repl = repl+1 acc = acc + val if (repl==expected) then print ("Current Value: ", acc/repl) end end for _,p in ipairs (peers) do rpc.async(p, "currValue", avrg)() endend

Page 41: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

comunicação um a um

• como pensar em canais ou mailboxes ondeprocessos espalhados por várias máquinaspodem recolher chamadas?

• no caso de tolerância a falhas: às vezesdesejável que os diversos processosrecebam a mesma chamada– replicação– comunicação em grupo

Page 42: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

tratamento de falhas

• como retornar informações sobre falhas nomodelo de chamada remota?– callbacks– exceções

Page 43: Chamada Remota de Procedimento (RPC)noemi/sd-08/aula4.pdf · 2008. 3. 18. · passo 3: criar uma especificação rpcgen /* rbd.x especificação rpc para um programa de banco de dados

objetos distribuídos

• invocação remota de métodos– objetos como unidades localizadas, argumentos, etc

or1.mx

processoservidor

or2.my

o.main()

ol1.ma ()

ol1.mb () ol1.mn ()

ol2.mm ()

processocliente

or1.mx(ol1) or2.mz