de escolhas não-determinísticas entre cápsulas, como no caso do interleaving. Um sinal de rollback é enviado para as cápsulas que não devem fazer parte do processo de sincroniza- ção, e suas referências são marcadas como free.
Quando pelo menos uma cápsula deve continuar o processo de sincronização, o método isRequested retorna true, e o estado do SystemController muda para locked. Neste ponto, pelo menos uma sub-cápsula ativa de SystemController está bloqueada. Neste estado, SystemController está pronta para receber os eventos a.rollback ou a.commit. Se o evento recebido for a.rollback, então todo o processo de sincronização é abortado. Se o evento recebido for a.commit, então todo o processo de sincronização deve ser concluído.
No caso do evento a.rollback, SystemController encaminha o evento recebido para todas as sub-cápsulas cujas referências estejam marcadas como locked, desbloqueando- as. O método forwardRollback encapsula a ação de encaminhar o evento para as sub- cápsulas marcadas. Em seguida, SystemController volta para o estado SC, onde estava antes do primeiro evento.
No caso do evento a.commit, SystemController encaminha o evento recebido para todas as sub-cápsulas cujas referências estejam marcadas como locked. Entretanto, se todo o processo de sincronização foi concluído, então possivelmente a equação expandida precisa ser atualizada. Suponha que a equação expandida seja P 2 Q. A conclusão do processo de sincronização com a cápsula Q implica que a cápsula P não será mais necessária. O método forwardCommit, executado na transição do evento a.commit, encapsula a ação de en- caminhar o evento para as sub-cápsulas marcadas, remover as cápsulas inutilizadas e atu- alizar a equação expandida. Em seguida, SystemController volta para o estado SC, onde pode processar qualquer evento de mudança de comportamento. Neste caso, a mudança de comportamento de todas as cápsulas que receberam o evento a.commit. Finalmente, a transição que gerencia a mudança de comportamento de P é adicionada ao estado SC de SystemController.
5.3 Aplicação da Estratégia de Prova sobre a Regra 5.1
Nesta seção, aplicamos a estratégia de prova sobre a Regra 5.1. A estratégia presente na Seção 5.1 é composta por dois passos. No primeiro passo, um processo em CSP é obtido através da tradução do lado direito da regra (Seção 5.3.1). No segundo passo, é provada a equivalência, no modelos de falhas e divergências, entre o processo obtido no primeiro passo e o processo que corresponde ao lado esquerdo da regra (Seção 5.3.2).
5.3.1 Tradução do Lado Direito da Regra 5.1
Inicialmente vamos apresentar a tradução dos protocolos CSPMessageProtocol (Figura 5.2) e CSPBehaviorProtocol (Figura 5.4). De acordo com a semântica atribuída a UML- RT no Capítulo 4, a tradução de um protocolo dá origem a um processo sem estado que captura o comportamento do protocolo e um canal para representar os elementos de comunicação. Em relação aos sinais, um único canal é utilizado para comunicar todos os sinais de um proto-
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 45
colo. Este canal comunica valores de um tipo enumerado, onde cada um de seus construtores representa um sinal. Além disso, admitimos que existe em CSP um tipo correspondente ao tipo de dados transmitido pelos sinais dos protocolos. Assim, consideramos que há em CSP um tipo Datatype, utilizado pelo sinal request de CSPMessageProtocol, e um tipo CSPExpression utilizado pelo sinal term de CSPBehaviorProtocol.
De acordo com a máquina de estados (Figura 5.3) do protocolo CSPMessageProtocol e com a semântica atribuída a UML-RT no Capítulo 4, o processo que representa este pro- tocolo seria naturalmente recursivo. As duas transições de saída (rollback e commit) do estado waiting commit retornam para o estado waiting requesting para que um novo ciclo de comunicação seja processado. No entanto, para efeito de prova, basta provarmos um ciclo de comunicação. Assim, o processo que representa este protocolo ter- mina em SKIP depois da ocorrência dos eventos rollback ou commit. O mapeamento do protocolo CSPMessageProtocol dá origem aos seguintes elementos: um tipo enu- merado TCSPMessageProtocol, cujos construtores representam os sinais deste protocolo, um canal
chanCSPMessageProtocol que transmite valores deste tipo, e um processo, de mesmo nome do
protocolo, que captura seu comportamento expresso pela máquina de estados da Figura 5.3. datatype TCSPMessageProtocol = request.Datatype | agreement |
commit | rollback channel chanCSPMessageProtocol: TCSPMessageProtocol CSPMessageProtocol =
chanCSPMessageProtocol.request?valor ->
chanCSPMessageProtocol.agreement ->
(chanCSPMessageProtocol.rollback -> SKIP []
chanCSPMessageProtocol.commit -> SKIP)
O mapeamento do protocolo CSPBehaviorProtocol é realizado da mesma maneira. Este mapeamento dá origem aos seguintes elementos: um tipo enumerado TCSPBehaviorProtocol, cujos construtores representam os sinais deste protocolo, um canal chanCSPBehaviorProtocolque transmite valores deste tipo, e um processo, de mesmo nome do protocolo, que captura seu comportamento expresso pela máquina de estados da Figura 5.5.
datatype TCSPBehaviorProtocol = term.CSPExpression channel chanCSPBehaviorProtocol: TCSPBehaviorProtocol
CSPBehaviorProtocol = chanCSPBehaviorProtocol.term?valor -> SKIP
A tradução do lado direito das regras envolve sempre duas cápsulas: a cápsula que re- presenta o processo P definido pela equação que corresponde ao lado esquerdo da regra, e a cápsula que representa o SystemController. Assim, considerando que os protocolos já foram traduzidos, quatro processos devem ser originados a partir desta tradução: o processo que representa o diagrama de estados da cápsula P, ChartP, o processo que representa a cápsula P propriamente dita, ou seja, seu diagrama de estrutura, StructP, o processo que representa o diagrama de estados da cápsula SystemController, ChartSystemController, e o processo que representa a cápsula SystemController propriamente dita, ou seja, seu diagrama de estrutura, StructSystemController.
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 46
A tradução da cápsula P da Regra 5.1 dá origem ao processo ChartP e ao canal b que representa a porta de mesmo nome. O tipo, TCSPBehaviorProtocol, deste canal é o mesmo do canal gerado pela tradução do protocolo, CSPBehaviorProtocol, que esta porta realiza. A máquina de estados da cápsula P possui apenas uma transição cuja origem é o estado inicial S0, e cujo destino é um estado sem transições de saída. Assim, o processo que representa
esta máquina de estados, ChartP, finaliza em SKIP, representando a tradução do estado sem transições de saída. Além disso, o processo SKIP é prefixado pelo evento b.term!N(s’), representando a tradução do estado S0que possui apenas uma transição de saída. Esta transição
não possui evento e, sua ação executa o sinal term da porta b, indicando que a cápsula P deve ser substituída pela cápsula N inicializada com o valor de s alterado para o de s’. O parâmetro s, de ChartP, representa o atributo de mesmo nome da cápsula P.
channel b: TCSPBehaviorProtocol
ChartP(s) = b.term!N(s’) -> SKIP
Para a formalização de cápsulas, é necessário considerar também o diagrama de estrutura. Neste caso, como a cápsula P não possui nenhuma subcápsula, então o processo que representa seu diagrama de estrutura, StructP, é idêntico ao processo que representa o seu diagrama de estados, ChartP.
StructP(s) = ChartP(s)
A cápsula SystemController da Regra 5.1 dá origem ao processo ChartSystemController e ao canal bP que representa a porta de mesmo nome. O tipo, TCSPBehaviorProtocol, deste canal é o mesmo do canal gerado pela tradução do protocolo, CSPBehaviorProtocol, que esta porta realiza. A tradução da máquina de estados da cápsula SystemController da regra 5.1 considera apenas o estado Sc, já que a transição do estado inicial S0para este estado não
possui ação associada. O estado Sc possui apenas uma auto-transição. Assim, o processo que representa esta máquina de estados seria traduzido para um processo recursivo. A ação corres- pondente a esta transição coordena a substituição da cápsula P pela cápsula cujo nome é re- presentado por N. O método replaceCapsule, executado na ação desta transição, remove a instância ativa da cápsula P, e cria uma instância ativa da cápsula N, usando o parâmetro s’. Em seguida, o método updateEquation atualiza a equação expandida corrente de SystemController, trocando a referência de P pela de N. Assim, esta ação é responsável por alterar a estrutura e o diagrama de estados de SystemController para que um novo ciclo se repita não mais com a cápsula P, mas agora com a cápsula N. Conseqüentemente, os processos que representam os diagramas de estrutura e estado de SystemController também seriam alterados. No entanto, para efeito de prova basta considerar um ciclo, assim, estamos preocupados apenas com este e não com o novo ciclo que se inicia. Assim, como o objetivo da ação desta transição é a criação de cápsulas opcionais, então a mesma é traduzida no evento activate.1, onde o índice 1 representa a ativação do processo correspondente à cápsula opcional instanciada. Este evento é prefixado por bP.term?p, representando a tradução do evento desta transição, o qual recebe informação de mudança comportamental através do sinal term da porta bP. Além disso, depois do evento activate.1 o processo ChartSystemController finaliza com sucesso (SKIP), já que vamos considerar apenas um ciclo de comunicação.
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 47
channel bP: TCSPBehaviorProtocol
ChartSystemController(s) = bP.term?p -> activate.1 -> SKIP
No processo StructSystemController, o processo ChartSystemControlleré sincronizado através do canal activate com o processo que ativa o comportamento do processo correspondente à cápsula N. A conexão entre a porta b, da cápsula P, e a porta bP, da cápsula principal SystemController, é simulada através da renomeação dos canais, que representam es- tas portas, para um canal comum. Assim, os canais bP, de ChartSystemController, e b, de StructP, necessitam ser renomeados com o nome k que representa o conector que liga a porta bP à porta b da cápsula P. Além disso, a ordem de execução dos sinais, imposta pelo protocolo que estas portas realizam, também deve ser considerada. Assim, o processo CSPBehaviorProtocol tem seu canal chanCSPBehaviorProtocol também renomeado com o nome do canal k, para que o comportamento deste processo seja sincronizado com os de ChartSystemController e StructP. Além disso, é necessário esconder os canais associados a conexões, portas protegidas de SystemController, e eventos de controle, visíveis somente no diagrama de estrutura de SystemController.
channel k: TCSPBehaviorProtocol cc = {|k|} hchan = cc ∪ {|bP|} ∪ {|activate|} StructSystemController(s) = ( ( ( ChartSystemController(s)[[bP ← k]] |[ {| activate |} ]| activate.1 -> N(s’) ) |[ cc ]| CSPBehaviorProtocol[[chanCSPBehaviorProtocol ← k]] ) |[ cc ]| StructP(s)[[b ← k]] ) \ hchan 5.3.2 Prova da Regra 5.1
Nesta seção vamos provar a Regra 5.1 apresentada na Seção 5.2. A prova é realizada no modelo de falhas e divergências através da aplicação de leis algébricas de CSP. A prova tem como ponto de partida o processo StructSystemControllerespecificado na Seção 5.3.1, já que a cápsula SystemController representa o comportamento do sistema como um todo, que neste caso é o comportamento do processo P especificado no lado esquerda da regra. O objetivo é provar a equivalência entre o processo StructSystemController e o processo correspondente ao lado direito da equação que especifica o processo P da regra em questão. Assim, para provar a Regra
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 48
5.1 precisamos provar a equivalência entre os processos StructSystemControllere N(s’). Por questões meramente didáticas, antes da aplicação de definições de processos ou leis algébricas de CSP, destacamos em negrito os termos sobre os quais as aplicações serão realizadas.
Assim, a prova da Regra 5.1 tem como ponto de partida o processo StructSystemController especificado na Seção 5.3.1. Nos três primeiros passos, aplicamos as definições dos proces- sos StructSystemController(s), ChartSystemController, CSPBehaviorProtocol, StructP e ChartP.
StructSystemController(s)
= {Definição de StructSystemController} ( ( ( ChartSystemController(s)[[bP ← k]] |[ {| activate |} ]| activate.1 -> N(s’) ) |[ {| k |} ]| CSPBehaviorProtocol[[chanCSPBehaviorProtocol ← k]] ) |[ {| k |} ]| StructP(s)[[b ← k]] ) \ {|k, bP, activate|}
= {Definição de ChartSystemController, CSPBehaviorProtocol e StructP} (
( (
(bP.term?p -> activate.1 -> SKIP)[[bP ← k]] |[ {| activate |} ]|
activate.1 -> N(s’) )
|[ {| k |} ]|
(chanCSPBehaviorProtocol.term?valor -> SKIP)[[chanCSPBehaviorProtocol ← k]] ) |[ {| k |} ]| ChartP(s)[[b ← k]] ) \ {|k, bP, activate|} = {Definição de ChartP} ( ( (
(bP.term?p -> activate.1 -> SKIP)[[bP ← k]]
|[ {| activate |} ]|
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 49
)
|[ {| k |} ]|
(chanCSPBehaviorProtocol.term?valor -> SKIP) [[chanCSPBehaviorProtocol ← k]]
)
|[ {| k |} ]|
(b.term!N(s’) -> SKIP)[[b ← k]]
) \ {|k, bP, activate|}
No próximo passo, utilizamos a Lei 2.2 ([[R]]-step) que aplica o operador de renomeação. = {Lei 2.2([[R]]-step)}
( (
(
k.term?p -> (activate.1 -> SKIP)[[bP ← k]] |[ {| activate |} ]|
activate.1 -> N(s’) )
|[ {| k |} ]|
k.term?valor -> SKIP[[chanCSPBehaviorProtocol ← k]] )
|[ {| k |} ]|
k.term!N(s’) -> SKIP[[b ← k]] ) \ {|k, bP, activate|}
A seguir, aplicamos novamente a Lei 2.2 ([[R]]-step) que captura a ocorrência da renomeação de eventos, assim como, a Lei 2.7 (SKIP-[[R]]-id) que elimina o operador de renomeação quando aplicado ao processo SKIP.
= {Leis 2.2 ([[R]]-step) e 2.7 (SKIP-[[R]]-id)} (
( (
k.term?p -> activate.1 -> SKIP[[bP ← k]]
|[ {| activate |} ]| activate.1 -> N(s’) ) |[ {| k |} ]| k.term?valor -> SKIP ) |[ {| k |} ]| k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 50
Mais uma vez, a Lei 2.7 (SKIP-[[R]]-id) é aplicada eliminando o operador de renomeação quando aplicado no processo SKIP.
= {Lei 2.7 (SKIP-[[R]]-id)} (
(
(
k.term?p -> activate.1 -> SKIP
|[ {|activate|} ]| activate.1 -> N(s’) ) |[ {| k |} ]| k.term?valor -> SKIP ) |[ {| k |} ]| k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
A sincronização entre dois processos compostos pelo operador de paralelismo generalizado é capturada através da aplicação da Lei 2.9 ( |[ X ]| -step).
= {Lei 2.9 ( |[ X ]| -step)} ( ( ( k.term?p -> ( activate.1 -> SKIP |[ {|activate|} ]| activate.1 -> N(s’) ) ) |[ {| k |} ]| k.term?valor -> SKIP ) |[ {| k |} ]| (k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
No próximo passo, aplicamos novamente a Lei 2.9 ( |[ X ]| -step). Neste caso, a sincronização será através do evento activate.1.
= {Lei 2.9 ( |[ X ]| -step)} (
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 51
(
k.term?p ->
activate.1 -> (SKIP |[ {|activate|} ]| N(s’)) ) |[ {| k |} ]| k.term?valor -> SKIP ) |[ {| k |} ]| (k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
Eventos do canal activate não fazem parte do alfabeto do processo N. Assim, pode- mos eliminar este canal do conjunto de sincronização da composição paralela entre SKIP e o processo N. = {{|activate|} 6⊂ αN} ( ( ( k.term?p -> activate.1 -> (SKIP |[ {} ]| N(s’)) ) |[ {| k |} ]| k.term?valor -> SKIP ) |[ {| k |} ]| (k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
De acordo com a definição do operador de interleaving presente no Capítulo 2, este ope- rador tem a mesma semântica do operador de paralelismo generalizado quando o conjunto de sincronização é vazio. Assim, no próximo passo, aplicamos a definição do operador de inter-
leaving. = {Definição de interleaving} ( ( ( k.term?p -> activate.1 -> (SKIP ||| N(s’)) ) |[ {| k |} ]| k.term?valor -> SKIP ) |[ {| k |} ]|
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 52
(k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
A seguir, aplicamos a Lei 2.23 (SKIP-|||-id) que elimina o processo SKIP do interleaving deste processo com outro processo qualquer.
= {Lei 2.23 (SKIP-|||-id)} ( ( ( k.term?p -> activate.1 -> N(s’) ) |[ {|k|} ]| k.term?valor -> SKIP ) |[ {| k |} ]| (k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
A lei que captura a sincronização entre dois processos compostos pelo operador de parale- lismo generalizado é aplicada no passo seguinte.
= {Lei 2.9 ( |[ X ]| -step)} ( ( k.term?p -> (activate.1 -> N(s’)) |[ {|k|} ]| SKIP ) |[ {| k |} ]| (k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
O operador de paralelismo generalizado é simétrico, a Lei 2.13 ( |[ X ]| -sym) captura este fato. Além disso, o processo SKIP pode ser retardado através da aplicação da Lei 2.10 ( |[ X ]| - preterm).
= {Leis 2.13 ( |[ X ]| -sym) e 2.10 ( |[ X ]| -preterm)} ( ( k.term?p -> activate.1 -> (SKIP |[ {|k|} ]| N(s’)) ) |[ {| k |} ]| (k.term!N(s’) -> SKIP
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 53
) \ {|k, bP, activate|}
O canal k foi criado pelo processo de tradução do lado direito da regra para representar conexão entre as cápsulas. Assim, eventos deste canal não fazem parte do alfabeto do processo N. Então este canal pode ser eliminado do conjunto de sincronização da composição paralela entre SKIP e o processo N.
= {{|k|} 6⊂ αN} ( ( k.term?p -> activate.1 -> (SKIP |[ {} ]| N(s’)) ) |[ {| k |} ]| (k.term!N(s’) -> SKIP ) \ {|k, bP, activate|} = {Definição de interleaving} ( ( k.term?p -> activate.1 -> (SKIP ||| N(s’)) ) |[ {| k |} ]| (k.term!N(s’) -> SKIP ) \ {|k, bP, activate|} = {Lei 2.23 (SKIP-|||-id)} ( ( k.term?p -> activate.1 -> N(s’) ) |[ {|k|} ]| k.term!N(s’) -> SKIP ) \ {|k, bP, activate|}
A sincronização através do canal k é capturada ao aplicarmos a Lei 2.9 ( |[ X ]| -step). = {Lei 2.9}
(
k.term?p ->
(activate.1 -> N(s’)) |[ {|k|} ]| SKIP
) \ {|k, bP, activate|}
O operador de paralelismo generalizado é simétrico (Lei 2.13 ( |[ X ]| -sym)). Além disso, o processo pode ser retardado através da aplicação da Lei 2.10 ( |[ X ]| -preterm).
5.3 APLICAÇÃO DA ESTRATÉGIA DE PROVA SOBRE A REGRA 5.1 54
= {Leis 2.13 ( |[ X ]| -sym) e 2.10 ( |[ X ]| -preterm)} (
k.term?p ->
activate.1 -> (SKIP |[ {|k|} ]| N(s’)) ) \ {|k, bP, activate|}
Os três próximos passos têm o objetivo de eliminar o processo SKIP da composição para- lela entre SKIP e o processo N. Eventos do canal k não fazem parte do alfabeto de N, assim, este canal pode ser eliminado do conjunto de sincronização. Este conjunto torna-se então vazio permitindo a aplicação da definição do operador de interleaving. Finalmente, eliminamos o processo SKIP através da aplicação da Lei 2.23 (SKIP-|||-id).
= {{|k|} 6⊂ αN} ( k.term?p -> activate.1 -> (SKIP |[ {} ]| N(s’)) ) \ {|k, bP, activate|} = {Definição de interleaving} ( k.term?p -> activate.1 -> (SKIP ||| N(s’)) ) \ {|k, bP, activate|} = {Lei 2.23 (SKIP-|||-id)} ( k.term?p -> activate.1 -> N(s’) ) \ {|k, bP, activate|}
Nos dois últimos passos, aplicamos a internalização de eventos utilizando a Lei 2.18 (hide- step). Além disso, no último passo, eliminamos o operador de internalização de eventos uma vez que eventos dos canias k, bP e activate não fazem parte do alfabeto do processo N. = {Lei 2.18 (hide-step)}
N(s’)\ {|k, bP, activate|} = {{|k, bP, activate|} 6⊂ αN}
N(s’) 2
5.3.3 Validação da Prova da Regra 5.1
De acordo com o que já foi dito anteriormente, utilizamos o model checker FDR para validar as provas das regras. A validação de cada prova corresponde em provar a equivalência, no modelo de falhas e divergências, entre o processo correspondente ao lado esquerdo da regra, ou seja, o processo P, e o processo correspondente ao modelo UML-RT do lado direito da regra, ou seja, o processo StructSystemController. A equivalência é provada fixando o processo P correspondente