Universidade Federal do Rio Grande do Norte Centro de Ciências Exatas e da Terra Departamento de Informática e Matemática Aplicada Programa de Pós-Graduação em Sistemas e Computação Dissertação de Mestrado Um Framework Baseado em Modelos Para Desenvolvimento de Sistemas Multimídia Distribuídos Autoadaptativos Felipe Alves Pereira Pinto Natal, Janeiro de 2011 Universidade Federal do Rio Grande do Norte Centro de Ciências Exatas e da Terra Departamento de Informática e Matemática Aplicada Programa de Pós-Graduação em Sistemas e Computação Um Framework Baseado em Modelos Para Desenvolvimento de Sistemas Multimídia Distribuídos Autoadaptativos Dissertação de Mestrado submetida ao Programa de Pós-Graduação em Sistemas e Computação do Departamento de Informática e Matemática Aplicada da Universidade Federal do Rio Grande do Norte como requisito para a obtenção do grau de Mestre em Sistemas e Computação (MSc.). Felipe Alves Pereira Pinto Prof. Dr. Adilson Barboza Lopes Orientador Natal, Janeiro de 2011 Catalogação da Publicação na Fonte. UFRN / SISBI / Biblioteca Setorial Especializada do Centro de Ciências Exatas e da Terra – CCET. Pinto, Felipe Alves Pereira. Um framework baseado em modelos para desenvolvimento de sistemas multimídia distribuídos autoadaptativos / Felipe Alves Pereira Pinto. – Natal, 2011. 91 f. : il. Orientador: Adilson Barboza Lopes. Dissertação (Mestrado) – Universidade Federal do Rio Grande do Norte. Centro de Ciências Exatas e da Terra. Departamento de Informática e Matemática Aplicada. Programa de Pós-Graduação em Sistemas e Computação. 1. Sistemas de processamento distribuído – Multimídia - Dissertação. 2. Desenvolvimento dirigido por modelos – Dissertação. 3. Framework autoadaptativo – Dissertação. I. Lopes, Adilson Barboza. II. Título. RN/UF/BSE-CCET CDU: 004.75 RESUMO Sistemas multimídia distribuídos possuem características bastante variáveis, podendo implicar em novos requisitos à medida que novas tecnologias são disponibilizadas ou na necessidade de adequação de acordo com a quantidade de recursos disponíveis. Dessa forma, tais aplicações devem ser capazes de realizar ajustes e adaptações dinâmicas, permitindo alterar sua estrutura e comportamento. Com o objetivo de prover capacidades de autoadaptação nesses sistemas, este trabalho apresenta uma abordagem de adaptação baseada em modelos. É proposto um framework reflexivo e baseado em componentes para a construção e suporte de sistemas multimídia distribuídos autoadaptativos, fornecendo várias facilidades para o desenvolvimento e evolução de tais sistemas, como adaptação dinâmica. A proposta do framework é manter um ou mais modelos de representação do sistema em tempo de execução, de modo que alguma entidade externa possa realizar uma análise desses modelos identificando problemas e tentando resolvê-los. Esses modelos integram o metanível reflexivo das aplicações atuando como uma autorrepresentação do sistema. Para isso, o framework define um metamodelo para a descrição de aplicações multimídia distribuídas autoadaptativas, o qual é capaz de representar componentes e seus relacionamentos, políticas para especificação de QoS e ações de adaptação. Adicionalmente, é proposta uma ADL e uma arquitetura para adaptação baseada em modelos. Como estudo de caso o trabalho apresenta alguns cenários buscando exemplificar o uso do framework na prática, com e sem o uso da ADL, bem como verificar algumas características relacionadas à adaptação dinâmica. Palavras-chave: sistemas multimídia distribuídos, adaptação, autoadaptação, framework, reflexivo, componentes, ADL, modelo, QoS, metamodelo. ABSTRACT Distributed multimedia systems have highly variable characteristics, resulting in new requirements while new technologies become available or in the need for adequacy in accordance with the amount of available resources. So, these systems should provide support for dynamic adaptations in order to adjust their structures and behaviors at runtime. This paper presents an approach to adaptation model-based and proposes a reflective and component-based framework for construction and support of self-adaptive distributed multimedia systems, providing many facilities for the development and evolution of such systems, such as dynamic adaptation. The propose is to keep one or more models to represent the system at runtime, so some external entity can perform an analysis of these models by identifying problems and trying to solve them. These models integrate the reflective metalevel, acting as a system self-representation. The framework defines a meta-model for description of self-adaptive distributed multimedia applications, which can represent components and their relationships, policies for QoS specification and adaptation actions. Additionally, this paper proposes an ADL and architecture for model-based adaptation. As a case study, this paper presents some scenarios to demonstrate the application of the framework in practice, with and without the use of ADL, as well as check some characteristics related to dynamic adaptation. Keywords: distributed multimedia systems, adaptation, self-adaptation, framework, reflective, component, ADL, model, QoS, meta-model. SUMÁRIO 1 2 INTRODUÇÃO ............................................................................................................... 11 1.1 Motivação ................................................................................................................... 13 1.2 Objetivos .................................................................................................................... 14 1.3 Contexto ..................................................................................................................... 15 1.4 Organização do Trabalho ........................................................................................... 16 REFERENCIAL TEÓRICO .......................................................................................... 18 2.1 Requisitos Para Adaptação Dinâmica ........................................................................ 18 2.2 Tipos de Adaptação Dinâmica ................................................................................... 19 2.3 Adaptação Baseada em Modelos ................................................................................ 20 2.4 Modelos de Componentes .......................................................................................... 22 2.5 Computação Reflexiva ............................................................................................... 23 2.6 Métricas Para Qualidade de Serviço .......................................................................... 24 2.6.1 Métrica de atraso unidirecional ........................................................................... 25 2.6.2 Métrica de perda de pacote unidirecional............................................................ 26 2.6.3 Métrica de variação do atraso unidirecional........................................................ 26 2.6.4 Métrica do atraso de ida e volta........................................................................... 27 2.7 Mecanismos de Comunicação .................................................................................... 27 2.7.1 Componentes locais em mesmo espaço de endereçamento ................................ 28 2.7.2 Componentes locais em diferentes espaços de endereçamento........................... 28 2.7.3 Componentes em diferentes máquinas físicas ..................................................... 29 3 FRAME ............................................................................................................................ 30 3.1 Metamodelo do FRAME ............................................................................................ 31 3.1.1 Especificação estrutural....................................................................................... 31 3.1.2 Especificação de QoS e autoadaptação ............................................................... 33 4 3.2 Arquitetura do FRAME .............................................................................................. 35 3.3 Modelo de Componentes ............................................................................................ 38 3.4 Estratégia de Autoadaptação ...................................................................................... 42 3.5 ADL ............................................................................................................................ 48 3.6 Protótipo Implementado ............................................................................................. 52 EXEMPLOS DE INSTANCIAÇÃO .............................................................................. 54 4.1 Modelando Uma Aplicação com a ADL Proposta ..................................................... 54 4.2 Abordagem Puramente Java Para a Criação de Aplicações ....................................... 58 4.3 Aplicações Adaptativas e Autoadaptativas ................................................................ 61 5 MEDIÇÕES INICIAIS ................................................................................................... 67 6 TRABALHOS RELACIONADOS ................................................................................ 69 6.1 Um Metamodelo Para QoS e sua Realização na Infraestrutura CORBA ................... 70 6.2 Um Framework Para Entrega Dirigido Por Qualidade .............................................. 71 6.3 PLASMA (PLAtform for Self-adaptive Multimedia Applications) ............................ 72 6.4 Um Framework Para Adaptações Multimídia Baseado em Redes Dinamicamente Configuráveis e Reconfiguráveis.............................................................................................. 74 7 6.5 PREMO (Presentation Environment for Multimedia Objects) .................................. 75 6.6 TOAST (Toolkit for Open Adaptive Streaming Technologies) .................................. 76 6.7 Análise Comparativa .................................................................................................. 78 CONCLUSÃO.................................................................................................................. 83 7.1 Trabalhos Futuros ....................................................................................................... 84 REFERÊNCIAS...................................................................................................................... 86 LISTA DE FIGURAS Figura 1 - Esquema para adaptação baseada em modelos. ....................................................... 21 Figura 2 - Metamodelo do FRAME. ........................................................................................ 31 Figura 3 - Arquitetura do FRAME mostrando seus componentes internos. ............................ 36 Figura 4 - Diagrama de classes para o modelo de componentes definido no FRAME. ........... 41 Figura 5 - Componentes arquiteturais e interfaces do modelo de componentes. ..................... 42 Figura 6 - Atividades do loop de controle, adaptado de [45]. .................................................. 43 Figura 7 - Diagrama de sequência mostrado os passos para trocar um componente. .............. 45 Figura 8 - Processo de adaptação para streaming multimídia. ................................................. 47 Figura 9 - Componente definido na ADL proposta. ................................................................. 49 Figura 10 - Exemplo da definição de um componente composto. ........................................... 50 Figura 11 - Exemplo completo de aplicação usando a ADL proposta. .................................... 51 Figura 12 - Uma aplicação definida com a ADL proposta. ...................................................... 55 Figura 13 - Definição adl.EncoderADL. .................................................................................. 56 Figura 14 - Script com ações para adaptação. .......................................................................... 57 Figura 15 - Definição adl.FreeDecoderADL. ........................................................................... 57 Figura 16 - Classe Calculator................................................................................................... 58 Figura 17 - Interface ICalculator. ............................................................................................ 58 Figura 18 - Criando a descrição da aplicação diretamente com a fábrica do framework. ........ 59 Figura 19 - Carregando a descrição e recuperando referências para o componente. ............... 60 Figura 20 - Mapeamento do modelo para a ADL. .................................................................... 61 Figura 21 - Descrição gerada pelo mapeamento feito pelo componente Model2ADL. ............ 61 Figura 22 - Especificação do estudo de caso (parte um). ......................................................... 62 Figura 23 - Especificação do estudo de caso (parte dois)......................................................... 63 Figura 24 - Especificação do estudo de caso (parte três). ........................................................ 64 Figura 25 - Interface application.cs.IService............................................................................ 64 Figura 26 - Implementação do componente server (appliation.cs.Server). ............................. 65 Figura 27 - Definição dos componentes para criptografia. ...................................................... 65 Figura 28 - Método principal da aplicação (main). .................................................................. 65 Figura 29 - Conjunto de janelas da aplicação. .......................................................................... 66 Figura 30 - Aplicação usada para medir o tempo de troca de um componente........................ 67 Figura 31 - Tempo para adaptação em 30 execuções. .............................................................. 68 Figura 32 - Tempo médio para adaptação. ............................................................................... 68 LISTA DE TABELAS Tabela 1 - Comparativo entre metamodelos. ............................................................................ 79 Tabela 2 - Comparativo entre as abordagens de middleware e framework apresentadas. ....... 80 LISTA DE ABREVIATURAS E SIGLAS ADL: Architecture Description Language API: Application Programming Interface CCM: CORBA Component Model CF: Component Framework COM: Component Object Model CORBA: Common Object Request Broker Architecture DBC: Desenvolvimento Baseado em Componentes DSML: Domain-Specific Modeling Languages EJB: Enterprise JavaBeans EMF: Eclipse Modeling Framework FRAME: Framework for Adaptive Multimedia Environments HTTP: Hypertext Transfer Protocol IDL: Interface Definition Language IETF: Internet Engineering Task Force IP: Internet Protocol IPDV: IP Packet Delay Variation IPPM: IP Performance Metrics ISO: International Organization for Standardization JMF: Java Media Framework JVLC: Java VideoLan Client MOP: MetaObject Protocol MOS: Mean Opinion Score MPEG: Moving Picture Experts Group NTP: Network Time Protocol OMG: Object Management Group OpenCOM: Open Component Object Model OpenORB: Open Object Request Broker POSIX: Portable Operating System Interface PREMO: Presentation Environment for Multimedia Objects QoS: Quality of Service RFC: Request for Comments RMI: Remote Method Invocation RM-ODP: Reference Model of Open Distributed Processing RPC: Remote Procedure Call RTP: Real-time Transport Protocol RTSP: Real Time Streaming Protocol RTT: Round-Trip Time TCP: Transmission Control Protocol UDP: User Datagram Protocol XML: Extensible Markup Language 11 1 INTRODUÇÃO Sistemas de software estão cada vez mais presentes no estilo de vida atual. Eles abrangem desde sistemas para uso doméstico, como um player de vídeo que pode ser usado para entretenimento, até sistemas complexos que envolvem aspectos financeiros como análise de riscos para aplicações na bolsa de valores, ou mesmo atividades médicas como o monitoramento de pacientes e uma possível interação remota de uma equipe médica através de videoconferência durante um procedimento cirúrgico. Obviamente, sistemas de software com objetivos distintos possuem requisitos igualmente distintos. Assim, por exemplo, um sistema de videoconferência usado durante um procedimento cirúrgico deve assegurar seus requisitos de confiabilidade, pois uma falha pode implicar na morte de alguém, enquanto que o travamento de um player usado por um usuário doméstico apenas irá aborrecê-lo. No caso dos sistemas distribuídos, além da diversidade das aplicações, outros fatores também devem ser considerados, como a confiabilidade e variabilidade das atuais infraestruturas de redes e o grande número de dispositivos capazes de executar esse tipo de aplicação, os quais muitas vezes possuem capacidades de processamento, memória e bateria limitados. Sistemas multimídia distribuídos agregam ainda mais complexidade, pois eles manipulam diferentes tipos de mídia de maneira integrada, incluindo áudio, vídeo e texto, sendo que cada uma delas possui requisitos diferenciados, exigindo certa QoS (Quality of Service) das infraestruturas de execução associadas, de forma que possam funcionar de maneira apropriada [1]. A complexidade destas aplicações torna-se ainda maior devido ao problema de heterogeneidade de hardware e software tão comum em sistemas distribuídos, principalmente em plataformas móveis ou com recursos limitados, como citado anteriormente. Sistemas multimídia distribuídos possuem características que são bastante variáveis, podendo implicar em novos requisitos à medida que novas tecnologias são disponibilizadas ou na necessidade de adequação de acordo com a quantidade de recursos disponíveis. Dessa forma, deve-se permitir a possibilidade dessas aplicações realizarem ajustes e adaptações dinâmicas que afetam sua estrutura e comportamento. Por adaptação dinâmica entendemos a capacidade de um sistema modificar sua estrutura e seu comportamento dinamicamente, em resposta a mudanças em seu ambiente de execução [2]. O termo reconfiguração será usado neste trabalho como sinônimo de adaptação e 12 ambos ocorrem em tempo de execução, enquanto uma configuração diz respeito a uma descrição de uma aplicação realizada estaticamente antes dela iniciar sua execução. Quando o sistema é capaz de monitorar parâmetros, por exemplo, parâmetros de QoS e de acordo com essas informações realizar adaptações, então consideramos esse sistema como autoadaptativo. O uso de adaptação dinâmica permite melhorar a disponibilidade de recursos em sistemas críticos, como no exemplo anterior do uso de videoconferência em procedimentos cirúrgicos, ou simplesmente tornar a interação do usuário com o sistema mais agradável, como seria o uso do player em uma aplicação doméstica de entretenimento. As três tecnologias chaves para o desenvolvimento de aplicações com suporte à adaptação dinâmica são [3]: separação de interesses, reflexão computacional e desenvolvimento baseado em componentes. O uso conjunto de reflexão computacional e desenvolvimento baseado em componentes tem sido adotado por várias abordagens [4][5][6][7], sendo também o ponto de partida deste trabalho. Um componente pode ser definido como uma unidade de software independente que encapsula seu projeto e implementação oferecendo serviços por meio de interfaces bem definidas [8]. Componentes podem ser usados não apenas para permitir a gerência e a composição de aplicações, mas também para permitir adaptações dinâmicas, considerando, por exemplo, a possibilidade de troca dessas unidades em tempo de execução. Desenvolver sistemas adaptativos usando a ideia de DBC (Desenvolvimento Baseado em Componente) é bastante difícil, por isso é comum esse tipo de abordagem fazer uso de modelos de componentes [9] que fornecem meios para controlar e conectar os componentes de um sistema. Com o objetivo de prover capacidades de autoadaptação em sistemas multimídia distribuídos, este trabalho usa uma abordagem de adaptação baseada em modelos. Modelos proporcionam facilidades para representar e especificar elementos de um sistema de software. Por exemplo, é possível usá-los para modelar o metanível reflexivo de sistemas autoadaptativos, permitindo especificar informações sobre a autorrepresentação do sistema envolvendo os componentes e seus relacionamentos, além de políticas ligadas a QoS e adaptação. É comum classificar modelos como concretos ou abstratos. Os modelos abstratos são chamados de metamodelos e especificam regras que determinam como devem ser os modelos concretos. Assim, podemos dizer que um metamodelo é instanciado em vários modelos concretos. Neste trabalho, usaremos a terminologia metamodelo e modelo, respectivamente, para indicar um modelo abstrato e um modelo concreto. Uma discussão mais detalhada sobre 13 essa terminologia é apresentada em [10]. 1.1 Motivação Como relatado anteriormente, desenvolver aplicações adaptativas é uma tarefa bastante complicada. No caso de sistemas multimídia distribuídos, além dos aspectos inerentes à distribuição e aos requisitos multimídia, ainda é preciso tratar questões relacionadas à adaptação dinâmica, por exemplo, operações de remoção, adição e troca de componentes e a manipulação sincronizada dos elementos do metanível, quando se trabalha com reflexão computacional. Atualmente, estas questões são tratadas pela maioria das plataformas de execução de aplicações multimídia incorporando conceitos de middleware, de maneira a facilitar o tratamento dos requisitos relacionados à distribuição e aos aspectos multimídia, bem como com a adaptação, de forma transparente. Uma adaptação dinâmica pode causar alterações estruturais no sistema com o objetivo de melhorar parâmetros relacionados ao desempenho e disponibilidade do sistema, por exemplo. Entretanto, tais mudanças devem ser realizadas de maneira coerente e segura, de modo que, não ocorram crashes no sistema, nem durante, nem após o processo adaptativo. Adaptações dinâmicas deveriam ser realizadas não apenas quando solicitadas por entidades externas, como um usuário, mas também de forma autônoma. Assim, o próprio sistema deve ser capaz de coletar informações e, através da análise dessas informações, decidir qual ação deve ser executada. Esse processo é executado em loop por sistemas autoadaptativos, sendo conhecido por feedback loops [11]. Várias pesquisas tratam estas questões, sendo a maioria das experiências desenvolvidas para sistemas distribuídos de uma maneira geral, sem considerar o domínio multimídia. Quando este é considerado, estas questões são tratadas de duas formas: a primeira concentra-se em definir a forma como as especificações de QoS e de adaptação são modeladas [12][13]; a segunda consiste em definir um framework, middleware, ou modelo de componentes, com o objetivo de prover suporte para operações de adaptação dinâmica, como adição e remoção de componentes [6][7][14][15]. Idealmente, uma abordagem completa deveria buscar integrar os dois interesses da melhor maneira possível em todas as fases do ciclo de vida do sistema, de forma a prover características autoadaptativas. Dessa forma, há uma necessidade evidente de desenvolver novas soluções que ofereçam facilidades para a construção de sistemas multimídia distribuídos autoadaptativos. No Capítulo 6, sobre trabalhos relacionados, são apresentadas algumas soluções para as questões levantadas, sendo realizada uma comparação entre elas e a abordagem apresentada 14 por este trabalho. 1.2 Objetivos O principal objetivo e contribuição deste trabalho é a concepção e implementação do FRAME (FRamework for Adaptive Multimedia Environments), um framework reflexivo e baseado em componentes, proposto para dar suporte à construção de sistemas multimídia distribuídos autoadaptativos. Para isso, o FRAME fornece facilidades para o desenvolvimento e evolução de tais sistemas, como distribuição transparente e adaptação dinâmica. Apesar do domínio em questão ser multimídia, a proposta é flexível o suficiente para ser usada em sistemas distribuídos de propósito geral. Há muitas definições para framework na literatura. Uma definição comum é que framework é um projeto reutilizável do todo ou parte de um sistema que é representado por um conjunto de classes abstratas e a forma como suas instâncias interagem. Outra definição comum é que framework é o esqueleto de uma aplicação que pode ser per personalizado por um desenvolvedor de aplicações. Estes conceitos não são conflitantes, simplesmente o primeiro deles descreve a estrutura de um framework, enquanto o segundo descreve sua proposta [16]. O conceito de framework adotado para o FRAME é compatível com as duas definições apresentadas. FRAME usa um esquema de adaptação baseado em modelos, similar a abordagem apresentada em [17]. A proposta consiste em manter um ou mais modelos de representação do sistema, em tempo de execução, de modo que alguma entidade externa possa realizar uma análise desses modelos de representação identificando problemas e tentando resolvê-los. Esses modelos integram o metanível reflexivo das aplicações atuando como uma autorrepresentação do sistema. Nesse tipo de abordagem, as entidades externas que analisam o modelo executam em loop tarefas de coleta de informações, análise dessas informações, decisão com base na análise e, finalmente, execução da adaptação. Nesse sentido, FRAME usa a ideia de feedback loops [11] para dar suporte a esse processo. Para dar suporte à abordagem de adaptação baseada em modelos, o framework proposto define um metamodelo para a descrição de aplicações multimídia distribuídas autoadaptativas. Esse metamodelo pode ser usado para definir os modelos que descrevem a autorrepresentação dos sistemas em tempo de execução. Em outras palavras, ele pode ser entendido como uma especificação para o metanível reflexivo desses sistemas, sendo capaz de representar componentes e seus relacionamentos, além de políticas para especificação de QoS e ações de adaptação. Além do metamodelo, o framework inclui uma ADL (Architecture Description 15 Language) baseada em XML (Extensible Markup Language) que permite descrever uma descrição textual do sistema. Essa descrição pode ser mapeada por um parser para um modelo conforme o metamodelo definido, bem como fornece um modelo de componentes com suporte para adaptação e reflexão que pode ser usado para a implementação dos componentes do sistema. O framework foi proposto para sistemas multimídia distribuídos autoadaptativos, porém ele é independente de aplicação específica e pode ser usado em outras situações, por exemplo, sistemas distribuídos que não façam uso do aspecto multimídia. A ADL integrada pode ser substituída por outra, desde que seja fornecido um parser que faça o mapeamento corretamente. A arquitetura definida para o framework dá suporte para a abordagem de adaptação baseada em modelos de uma forma geral, sendo possível, por exemplo, usar a mesma arquitetura com outros metamodelos ou ADL. Assim, resumidamente, podemos destacar: 1. A concepção e implementação desse framework (FRAME) como o principal objetivo deste trabalho, sendo também a principal contribuição fornecida; 2. O metamodelo e a ADL proposta, além da arquitetura para adaptação baseada em modelos, como objetivos e contribuições secundárias, pois não são dependentes do framework e podem ser reusados por outras abordagens. 1.3 Contexto O presente trabalho está inserido no grupo de pesquisa em Sistemas Distribuídos orientado pelo Prof. Dr. Adilson Barboza Lopes, lotado no Departamento de Informática e Matemática Aplicada da Universidade Federal do Rio Grande do Norte. O principal trabalho desenvolvido nesse grupo apresenta o Cosmos [18], um framework para configuração e gerenciamento de recursos e componentes em sistemas multimídia distribuídos abertos. A seguir, são apresentadas as principais diferenças entre o presente trabalho e as outras propostas apresentadas anteriormente pelo grupo. Desde a proposta inicial do Cosmos, alguns trabalhos foram desenvolvidos no intuito de tratar suas limitações [19][20][21]. Ainda assim, várias questões continuam abertas, por exemplo, o suporte efetivo à adaptação dinâmica, considerando adição e remoção de componentes. Outras características foram apenas parcialmente implementadas e ainda precisam ser aperfeiçoadas antes de serem disponibilizadas para uso externo ao grupo, como é o caso do modelo de especificação de QoS. FRAME, apesar de ser um novo framework, pode ser considerado como uma evolução do framework Cosmos, sendo resultado de um processo de reengenharia, onde buscamos 16 reestruturar o Cosmos considerando a experiência desenvolvida pelo grupo nesse domínio, resolvendo limitações e incorporando novos requisitos como, por exemplo, autoadaptação. É importante notar que o FRAME fornece uma abordagem de adaptação mais flexível e mais dinâmica do que o Cosmos. Além de dar suporte à troca de componentes, ele permite a definição e uso de políticas dinâmicas, ou seja, é possível alterar em tempo de execução informações relacionadas à especificação de QoS e das ações de adaptação, podendo inclusive não apenas alterar partes da política em questão, mas também substituí-la integralmente por outra. No Cosmos as políticas são definidas estaticamente e não mudam durante a execução. Outro trabalho recente do grupo [22] apresenta uma abordagem de middleware baseado em componentes, através do desenvolvimento dirigido por modelos, que provê à aplicação abstração da comunicação entre os componentes envolvidos em um fluxo de dados, independente da localização deles. O foco desse trabalho é definir metamodelos que permitem gerar implementações de diferentes middlewares multimídia. Esses middlewares dão suporte à autoadaptação do mecanismo de comunicação utilizado, seja através da atualização dos valores dos seus parâmetros de configuração, ou através da substituição por outro mecanismo, caso as restrições de qualidade de serviço especificadas não estejam sendo fornecidas. Nesse sentido, uma das adaptações tratadas na proposta [22] é alterar o protocolo de comunicação usado, por exemplo, de TCP (Transmission Control Protocol) para UDP (User Datagram Protocol). Essa proposta apresenta uma abordagem para adaptação dinâmica limitada ao mecanismo de comunicação usado para streaming entre componentes produtores e consumidores. O FRAME apresenta uma abordagem mais genérica fornecendo um modelo de componentes que permite a troca dos componentes da aplicação, de forma que diversas mudanças comportamentais e estruturais possam ser realizadas, não se limitando, assim, apenas ao nível de comunicação. Outra diferença é que o metamodelo definido pelo FRAME é proposto para ser uma especificação do metanível reflexivo e não para geração da implementação do framework propriamente dito. 1.4 Organização do Trabalho O restante do trabalho está organizado da seguinte forma: o Capítulo 2 discute alguns conceitos iniciais necessários ao entendimento da proposta, compreendendo os requisitos e tipos de adaptação dinâmica, adaptação baseada em modelos, mecanismos de comunicação, métricas para qualidade de serviço, computação reflexiva e desenvolvimento baseado em componentes; o Capítulo 3 apresenta o framework proposto, bem como sua arquitetura, o metamodelo definido, estratégia para autoadaptação, ADL, modelo de componentes e o protótipo implementado; o Capítulo 4 descreve exemplos de instanciação do framework, 17 definindo alguns estudos de casos; o Capítulo 5 apresenta algumas medições iniciais sobre o tempo de adaptação do framework; o Capítulo 6 resume alguns trabalhos relacionados e realiza uma análise comparativa entre eles e a presente proposta; finalmente, o Capítulo 7 apresenta a conclusão, com algumas indicações de trabalhos futuros. 18 2 REFERENCIAL TEÓRICO Este capítulo introduz alguns conceitos básicos fundamentais para o entendimento deste trabalho. Serão abordados a seguir os principais conceitos e requisitos relacionados à adaptação dinâmica, além dos tipos de adaptação mais comuns, adaptação baseada em modelos, modelos de componentes, computação reflexiva e algumas métricas para qualidade de serviço e mecanismos de comunicação. 2.1 Requisitos Para Adaptação Dinâmica Para que ocorra uma adaptação dinâmica com sucesso em um sistema alguns requisitos devem ser atendidos. Deve-se considerar que um dos fatores que tornam a adaptação dinâmica mais difícil de realizar diz respeito ao fato das aplicações terem estado. Dessa forma, nos sistemas baseados em componentes, tantos os componentes do sistema como as interações entre eles podem possuir estado. Considerando o estado dos componentes, podemos classificá-los de duas formas [23]: Stateful: componentes que mantém informações relacionadas ao estado. A consistência dessas informações é necessária para manter o componente e o sistema como um todo funcionando corretamente. Dessa forma, quando se deseja trocar um componente stateful, primeiro deve-se transferir o estado do componente antigo para o novo componente substituto; Stateless: componentes que não mantém informações relacionadas ao estado. Esses componentes podem ser trocados seguindo uma abordagem bem mais simples que os stateful, pois não é preciso considerar a transferência de estado nesse caso. Para realizar a troca de um componente stateful deve-se encontrar um ponto seguro durante a execução para extrair seu estado. É preciso observar que o estado do componente deve ser o mesmo durante o processo de transição e que todas as chamadas realizadas ao componente, ou originadas por ele, são potenciais produtores de alteração de estado. Uma solução simples é congelar todo o sistema, realizar a transferência do estado e, em seguida, substituir o componente. Obviamente, tal solução não é viável, pois traz um impacto grande na execução do sistema, tornando-o completamente indisponível durante o processo de adaptação, principalmente quando consideramos sistemas com requisitos de tempo real, como os sistemas multimídia. Idealmente, um número mínimo de componentes do sistema deveria ser parado garantindo que o estado do componente alvo da troca mantenha-se inalterado. Para que isto aconteça, duas condições são necessárias [23]: 19 O componente não está atendendo chamadas no momento; O componente não tem chamadas em execução e não irá iniciar chamadas. Nestas condições, diz-se que o componente possui estado quiescent, termo inicialmente definido em [24]. Assim, quando o estado do componente for quiescent, significa que este é um momento seguro para realizar a adaptação dinâmica. Obviamente, garantir o estado quiescent, bem como realizar o processo adaptativo é uma tarefa complexa, principal motivo pelo qual as plataformas de suporte para desenvolvimento de aplicações adaptativas deveriam tornar esse processo o mais transparente possível ao desenvolvedor. Dessa forma, considerando o que foi discutido, é possível destacar quatro requisitos chaves para adaptação dinâmica [25]: Corretude: a adaptação deve ser executada resultando na correta evolução do sistema, de forma que os componentes afetados ou não pelo processo continuem funcionando corretamente e com seus estados consistentes; Adequabilidade geral: a abordagem proposta para adaptação deve ser genérica sem se prender a um determinado tipo de componente, por exemplo, componentes multithread ou single-thread, stateful ou stateless, etc; Mínimo impacto na execução: durante a adaptação apenas os elementos afetados devem ser parados, de modo que os demais serviços do sistema continuem disponíveis; Máxima transparência: a adaptação deve ser o mais transparente possível para o desenvolvedor do sistema e dos componentes do sistema. 2.2 Tipos de Adaptação Dinâmica Adaptação dinâmica diz respeito a reconfigurações no sistema em tempo de execução. Essas reconfigurações podem ser aplicadas de algumas maneiras, entre elas, destacamos três principais tipos [6][26]: Reconfiguração funcional: é a forma mais básica de reconfiguração, consistindo na mudança de atributos dos componentes. Esses atributos influem diretamente no comportamento do componente; por exemplo, seria possível mudar o fator de qualidade de codificação ou o framerate usado por um componente codificador; Reconfiguração estrutural: este tipo de adaptação atua na forma como os componentes compõem o sistema. Envolve operação como adição, remoção e troca de componentes; Reconfiguração de políticas: uma adaptação não precisa necessariamente atuar apenas 20 nos atributos dos componentes ou na estrutura do sistema, ela pode também afetar as próprias políticas de adaptação definidas para o sistema. Mudanças nesse sentido podem alterar, por exemplo, os intervalos de monitoramento dos componentes, ou incluir novas regras nas políticas de QoS, bem como definir novas ações de adaptação para determinadas situação. Eventualmente, a política inteira pode ser trocada se for conveniente. Durante a execução do sistema pode acontecer de um novo tipo de serviço ficar disponível, ou então um serviço antigo tornar-se indisponível. Assim, o sistema deve ser capaz de detectar e usar esses novos serviços e parar o uso dos antigos que se tornaram indisponíveis [26]. Esse caso enquadra-se na reconfiguração estrutural já que afeta a estrutura do sistema. Porém, essa situação específica envolve uma complexidade bem maior, pois é necessário monitorar o ciclo de vida dos componentes e tomar ações corretivas quando eles tornarem-se indisponíveis, bem como definir algum mecanismo para que novos componentes registrem seus serviços providos e o sistema saiba quando um novo serviço for disponibilizado. Vale ressaltar que nesses casos a adaptação é global, no sentido que, quando um serviço torna-se indisponível, todos os componentes do sistema que usam esse serviço devem ser notificados e, consequentemente, parar de usá-lo. Dessa forma, também é necessário diferenciar quais serviços são opcionais, sendo possível continuar sem eles, e quais serviços são obrigatórios, sendo impossível prosseguir a execução caso eles tornem-se indisponíveis. Os três tipos de adaptação mostrados são bastante comuns em propostas de infraestruturas adaptativas, sejam elas baseadas simplesmente em um modelo de componentes, ou em propostas mais abrangentes como sistemas de middleware ou frameworks. O foco do FRAME, com relação aos tipos de adaptação apresentados, é dar suporte aos três tipos. Porém, ele ainda não contemplará a situação específica discutida para reconfiguração estrutural, na qual é preciso detectar novos serviços, bem como a eventual indisponibilidade dos antigos. 2.3 Adaptação Baseada em Modelos O framework proposto usa uma abordagem para adaptação baseada em modelos que será mostrada a seguir. Esse esquema é independente de ADL, linguagens de programação ou aplicações específicas. Na maioria das abordagens os mecanismos usados para adaptação são incorporados no escopo da aplicação e ligados ao seu código. Nessas abordagens, possíveis falhas no sistema 21 podem ser capturadas imediatamente quando ocorrem, por exemplo, através do tratamento de exceções fornecido pelas linguagens de programação. Porém, as falhas são tratadas de maneira localizada e o sistema pode não ser capaz de determinar a origem real do problema. Esse tipo de solução dificulta o monitoramento de algumas anomalias, como a degradação gradual do desempenho, e torna bastante difícil realizar reconfigurações nas políticas de adaptação, já que geralmente elas estão entrelaçadas no código do sistema [17]. O trabalho apresentado em [17] defende uma abordagem alternativa com base no uso de modelos, de forma a “externalizar” a adaptação. O uso de modelos apresenta algumas vantagens: Do ponto de vista da aplicação, esta abordagem permite escolher qualquer modelo disponível que melhor possa representá-la; Devido ao nível de independência entre modelo e aplicação existe um suporte maior para reuso; Os modelos podem ser facilmente modificados; É possível explorar e analisar os modelos, em tempo de execução, buscando melhorar requisitos ligados ao desempenho, confiabilidade e segurança, por exemplo; É possível realizar transformações automatizadas e gerar parte da implementação do sistema, ou ainda, usar o metamodelo como base para a definição de DSMLs (Domain-Specific Modeling Languages) [27]. A Figura 1 apresenta um esquema para adaptação baseada em modelos, inspirada na abordagem definida em [17] e adaptada pelo presente trabalho para incluir o metamodelo e a ADL propostos pelo FRAME. Deve-se notar que o modelo e as entidades que realizam a adaptação são externos ao sistema. Dada essa característica, fazemos uso do termo adaptação “externalizada”. Esse também é o esquema usado na proposta do framework FRAME. Figura 1 - Esquema para adaptação baseada em modelos. 22 Nesse esquema, o sistema é representado por um modelo, sendo este definido conforme um metamodelo. São definidas entidades externas como gerentes, monitores e parsers, que coletam e analisam informações do modelo e realizam alterações nele quando necessário. Uma entidade externa é qualquer elemento, exceto o metamodelo, externo ao sistema e independente dele. Por outro lado, deve-se assegurar que as mudanças realizadas no modelo sejam refletidas no sistema, ou seja, devem provocar adaptações. Essa abordagem permite que uma ADL seja usada para a especificação do sistema, de forma que no lançamento deste, um parser possa extrair informações dessa descrição e passálas às entidades externas, que por sua vez, mapeiam essas informações para as estruturas do modelo. Durante a execução do sistema, scripts com ações de adaptação podem ser submetidos às entidades externas permitindo que elas executem as alterações necessárias no modelo e efetivem a adaptação no sistema. Por fim, nos sistemas autoadaptativos é provável que, ao longo do tempo, devido às adaptações sucessivas, a especificação original da arquitetura não mais reflita o estado atual do sistema. Nesse caso seria interessante realizar uma reconstrução dessa especificação arquitetural [28]. Nesse sentido, as entidades externas podem coletar informações do modelo com o objetivo de gerar uma especificação atualizada usando a ADL em questão. Observando a Figura 1, destacamos que este trabalho irá definir um framework (FRAME) que dê suporte ao esquema de adaptação baseado em modelos apresentado. Logo, FRAME define um metamodelo para descrever modelos de sistemas específicos, bem como uma ADL e um conjunto de entidades externas, como monitores, gerentes de adaptação e parsers. 2.4 Modelos de Componentes O desenvolvimento baseado em componentes é um importante tópico na engenharia de software. Vários trabalhos têm definido modelos de componentes e, entre eles, podemos citar: OpenCOM (Open Component Object Model) [4], Fractal [5], CCM (CORBA Component Model) [29], EJB (Enterprise JavaBeans) [30] e COM (Component Object Model) [31]. De acordo com [32] um modelo de componentes fornece a definição semântica, sintática e composicional dos componentes. A semântica dos componentes indica o que significa ser um componente para esse modelo. Por exemplo, um componente EJB é uma classe Java que implementa interfaces bem definidas, sendo hospedada e gerenciada em um contêiner. Em outros casos, o modelo pode considerar um componente como uma unidade arquitetural que requer e fornece serviços por meio de elementos como portas ou interfaces. Exemplo desse caso é o CCM. 23 A sintaxe dos componentes diz como eles são definidos, construídos e representados. A definição de um componente requer uma linguagem de descrição de componentes. Por exemplo, o modelo COM usa uma IDL (Interface Definition Language) definida pela Microsoft, enquanto o CCM usa uma IDL definida pela OMG (Object Management Group). Outros modelos, como é o caso do Fractal, possuem uma ADL para este fim. Comumente a linguagem para descrição de componentes é diferente da linguagem de implementação do sistema, entretanto em alguns modelos ela acaba sendo apenas uma API (Application Programming Interface) definida na linguagem de programação do sistema, como é o caso do OpenCOM que possui implementações dessa API em Java e C++. O modelo Fractal também possui uma API semelhante, sendo possível decidir entre ela e a ADL fornecida. A composição dos componentes diz como eles são compostos ou montados. A composição envolve questões de como os componentes são construídos, se são usados repositórios, como eles são montados e conectados para formar o sistema ou um componente maior. Nesse sentido, para definir composições é necessário uma linguagem com semântica e sintaxe adequadas. EJB, COM e CCM não possuem linguagens para composição [32]. ADLs fornecem linguagens de composição formais, de modo que modelos como Fractal, que permitem usar uma ADL para descrição arquitetural, possuem suporte à composição. Já modelos como o OpenCOM, no qual a arquitetura é definida usando uma API Java ou C++, também é de se esperar que a composição seja feita usando essa API. Nesta situação, o suporte à composição também é fornecido, ainda que essas linguagens não sejam adequadas para tal finalidade. O conjunto de definições de um modelo de componentes (semântica, sintaxe e composição) deve dar suporte ao desenvolvimento de aplicações baseadas em componentes. Em [5] são definidos requisitos chaves que devem ser suportados por um modelo de componentes genérico, sendo eles: encapsulamento, identificação unívoca entre os componentes, composição, compartilhamento de recursos, gerenciamento de ciclo de vida dos componentes, adaptabilidade, apoio à execução de atividades e meios de realizar seu controle através de componentes com capacidades introspectivas. O framework proposto por este trabalho (FRAME) é independente de aplicação específica e, em consequência, o modelo de componentes definido por ele também é. Dessa forma busca-se dar suporte aos requisitos apresentados anteriormente através de seu modelo de componentes e da ADL fornecida. 2.5 Computação Reflexiva Reflexão computacional refere-se à capacidade de um programa manter informações 24 sobre ele mesmo e, devido isso, ser capaz de raciocinar com base nessas informações e alterar seu próprio comportamento. A reflexão permite ao sistema revelar certos detalhes da sua implementação sem comprometer a portabilidade [3]. A computação reflexiva compreende duas atividades [3]: Introspecção: permite que o sistema observe seu próprio comportamento e estrutura; Intercessão: permite ao sistema agir com base em suas observações, alterando seu comportamento e sua estrutura. Reflexão computacional, aliada ao desenvolvimento baseado em componentes, é uma forte estratégia para o suporte a construção de sistemas autoadaptativos. Por exemplo, monitores podem usar introspecção para observar e reportar variações dos componentes, enquanto gerentes com base nessas informações podem usar a intercessão para inserir novos monitores ou novos componentes e executar ações corretivas em tempo de execução. Um sistema reflexivo é formado por dos níveis. O primeiro é o nível base, constituído pelos componentes de base que são o sistema em si. O segundo é o metanível que atua como uma descrição/autorrepresentação do sistema, ou seja, do nível base, sendo formado por componentes de metanível, ou metacomponentes. Esses dois níveis são causalmente conectados, ou seja, modificações em um deles devem ser refletidas no outro. Nesse sentido, é comum falar de reificação, conceito associado ao processo de alteração do nível base. Nesses sistemas existe o conceito de MOP (MetaObject Protocol). MOP é um protocolo, na verdade formado por um conjunto de interfaces, que permitem acesso ao metanível através das operações de introspecção e intercessão. MOP deve suportar reflexão estrutural e comportamental. A primeira esta relacionada aos componentes do sistema e seus relacionamentos, enquanto a segunda foca a semântica da aplicação. Há várias maneiras de fazer uso de reflexão computacional no desenvolvimento de um sistema. Os desenvolvedores podem usar recursos nativos de linguagens de programação, como Python e Java, por exemplo, ou ainda providos por alguma plataforma. É comum propor suporte para reflexão de forma integrada com modelos de componentes, middlewares ou frameworks, conforme foram citados alguns exemplos anteriormente. Em particular, o FRAME, proposto por este trabalho, também é um framework reflexivo. 2.6 Métricas Para Qualidade de Serviço O gerenciamento de parâmetros de QoS é importante, por exemplo, para avaliar o desempenho de aplicações de tempo real na Internet. Porém o comportamento imprevisível desta dificulta a obtenção de algumas dessas métricas. A avaliação do desempenho de uma aplicação que troca informações pela rede pode 25 depender do tipo da informação enviada em seus pacotes. Para algumas aplicações, esse desempenho pode depender principalmente da qualidade do serviço em cada direção ou apenas em uma direção. Dessa forma, é comum falar sobre métricas IP (Internet Protocol). Métricas IP unidirecionais são aquelas que medem o desempenho do protocolo IP em apenas um sentido. Essas métricas são necessárias para caracterizar o estado dos caminhos entre os hosts, pois as rotas podem ser assimétricas, ou seja, o caminho de um pacote que trafega num sentido pode diferir do caminho de um pacote que trafega no sentido inverso. Além disso, mesmo que os caminhos de ida e volta sejam simétricos, o enfileiramento dos pacotes pode sofrer variações. A IETF (Internet Engineering Task Force) [33] possui um grupo de trabalho, conhecido por IPPM (IP Performance Metrics) [34], que trata de métricas de desempenho para o protocolo IP. O grupo IPPM tem produzido documentos que especificam essas métricas de desempenho e propõem metodologias para o seu cálculo. O conjunto das métricas unidirecionais é formado pelo atraso em um sentido, a sua variação e a perda de pacotes em um sentido. As métricas citadas acima mais um parâmetro que indica o tempo de ida e volta de um pacote na rede, foram as contempladas por este trabalho no contexto de gerenciamento e monitoramento da comunicação. Obviamente, deve ser possível para cada componente definir propriedades que indiquem novos parâmetros que devem ser gerenciados e monitorados de forma automatizada como, por exemplo, a carga de processamento e o consumo de memória do componente, o que também pode influenciar na qualidade de serviço final. Deve ficar claro que não faz parte do escopo deste trabalho realizar a implementação das metodologias de cálculo definidas nos documentos RFC (Request for Comments) da IETF. O framework proposto permite a recuperação e monitoramento de parâmetros de QoS, calculados com base nessas métricas, desde que elas sejam fornecidas pelo protocolo atualmente usado na comunicação ou internamente pelo componente em questão, como seria o exemplo do consumo de memória, citado anteriormente. A seguir serão apresentadas as métricas definidas para comunicação. 2.6.1 Métrica de atraso unidirecional O atraso unidirecional, também muito conhecido por latência, é definido pela IPPM na RFC2679 [35]. Essa métrica pode ter um valor indefinido ou um valor real medido em segundos. O termo atraso unidirecional é mais preciso do que latência, no entanto, sempre que usarmos o termo latência neste trabalho, no sentido de um parâmetro da transmissão, estaremos nos referindo ao atraso unidirecional. 26 O atraso em um sentido é definido por um número real dT que significa o tempo transcorrido desde o momento em que um host origem envia o primeiro bit de um pacote para o destino, no instante T, e o destino recebe o último bit desde pacote, no instante T + dT. O atraso é dito indefinido (informalmente infinito) quando o host de origem envia o primeiro bit do pacote e o destinatário não recebe o pacote. Para obtenção dessa métrica, tanto o host de origem como o de destino precisam ter os relógios sincronizados com uma boa precisão. O NTP (Network Time Protocol) [36] é um protocolo auxiliar que fornece mecanismos para realizar tal sincronização. 2.6.2 Métrica de perda de pacote unidirecional A perda unidirecional ocorre quando o pacote enviado pela origem não chega ao destino. Quando ocorre fragmentação de um pacote, a perda é caracterizada se pelo menos um dos fragmentos é perdido. Esta métrica é definida na RFC2680 [37] pela IPPM. Assim, como na métrica de atraso, algumas aplicações não funcionam corretamente se a perda de pacotes entre os hosts for relativamente alta. O valor desta métrica pode ser zero, indicando sucesso na transmissão do pacote, ou um, indicando perda do pacote. Pacotes duplicados devem ser computados como recebidos e pacotes fragmentados que foram parcialmente recebidos ou corrompidos são computados como não recebidos. Falando de maneira informal, ocorre perda de um pacote quando o atraso unidirecional para este pacote é infinito. 2.6.3 Métrica de variação do atraso unidirecional Apenas o atraso unidirecional não é suficiente para definir a qualidade de uma transmissão, pois as redes não conseguem garantir uma taxa de entrega constante dos pacotes ao destino. Então, a IPPM definiu uma medida da variação do atraso unidirecional especificada na RFC3393 [38] como IPDV (IP Packet Delay Variation). A variação do atraso é normalmente chamada de jitter. Este termo, entretanto, provoca certa confusão, pois pode ser usado de diferentes maneiras por diferentes grupos de pessoas. O termo jitter comumente tem dois significados: 1. A variação de um sinal com relação a algum sinal de relógio. Este significado é usado com referência a sinais síncronos e pode ser usado para medir a qualidade de emulação de um circuito, por exemplo; 2. Simplesmente se refere à variação de alguma métrica. Este significado é frequentemente usado por cientistas da computação e, em geral, a métrica a que se refere é o atraso unidirecional. Nesse trabalho sempre que usarmos o termo jitter estaremos usando o segundo 27 significado, referindo-se a variação do atraso unidirecional, ou seja, como sinônimo de IPDV. O IPDV é definido como a diferença entre os atrasos de um par de pacotes e, ao contrário do atraso, ele independe da sincronização de fase dos relógios quando calculado para pacotes consecutivos, ou seja, se os relógios de ambos os hosts marcam a mesma hora. Ainda assim, esse cálculo depende da sincronização de frequência dos relógios, ou seja, se um relógio atrasa ou adianta em relação ao outro com o passar do tempo. De qualquer forma, o erro de sincronização na frequência é de várias ordens de magnitude inferior ao valor medido e pode ser ignorado. Isso permite fazer cálculos de IPDV entre pacotes consecutivos mesmo sem garantias de sincronização de relógios. O IPDV será dado por um número real com unidade em segundos, ou um valor indefinido no caso de ocorrer perda de um dos pacotes selecionados para medição. 2.6.4 Métrica do atraso de ida e volta Essa métrica, também muito conhecida por RTT (Round-Trip Time), é definida pela IPPM na RFC2681 [39] com o título Round-trip Delay. Ela mede o tempo que um pacote leva para dar uma volta completa, ou seja, ser enviado pela máquina de origem, recebido pela máquina de destino e devolvido por esta para a máquina de origem. O valor dessa métrica é um número real medido em segundos. Quando o pacote enviado pela origem não chega ao destino, ou quando o destino não envia a resposta, ou quando a origem não recebe a resposta enviada, considera-se que o valor para a medição é indefinido, informalmente, infinito. O cálculo para essa métrica é consideravelmente simples, pois todos os tempos são medidos apenas no host de origem. Assim, considere que o host origem enviou um pacote para o host destino no instante T1src, medido na origem. O host destino recebeu o pacote e enviou de volta para o host origem, sendo que este recebeu a resposta no instante T2src, também medido na origem. Dessa forma, o RTT é dado por dT = T2src – T1src. Esta é a forma recomendada pela IPPM para cálculo dessa métrica. Deduzi-la com base na latência, que é medida apenas em uma direção, é um erro, pois o tempo de volta do pacote não necessariamente é o mesmo da ida, sem contar que os caminhos de ida e volta podem ser assimétricos. 2.7 Mecanismos de Comunicação A escolha de um mecanismo adequado para realizar a comunicação entre dois ou mais componentes depende, entre outros fatores, da localização de cada um deles. Os mecanismos de suporte devem ser providos de forma a proporcionar para a aplicação transparência de comunicação e, idealmente, devem ser selecionados os melhores mecanismos no contexto 28 atual da plataforma considerando os requisitos do sistema segundo uma visão integral. Existem alguns mecanismos, como RMI (Remote Method Invocation) e RPC (Remote Procedure Call), que proporcionam transparência de comunicação, mas não são adequados para a situação em que os componentes são locais, pois eles usam métodos direcionados para comunicação remota. Nesse contexto, o texto levanta algumas questões sobre os possíveis cenários de localização analisando as maneiras mais adequadas para realizar a comunicação em cada cenário. 2.7.1 Componentes locais em mesmo espaço de endereçamento Este é o caso mais simples. Para essa situação, a melhor solução consiste em obter as referências locais dos componentes envolvidos, permitindo assim a realização de comunicação direta uma vez que eles estão no mesmo espaço de endereçamento. Essa situação é comum na realização de comunicação em sistemas multi-thread. Quando se trabalha com linguagens que usam máquinas virtuais é comum referir-se ao caso como componentes locais na mesma máquina virtual. 2.7.2 Componentes locais em diferentes espaços de endereçamento Esse cenário envolve um nível de complexidade maior do que o caso anterior uma vez que as soluções mais eficientes são dependentes de plataforma e usam APIs nativas do sistema operacional. Em projetos de sistemas multimídia que envolvem softwares embarcados, diferentes mecanismos de comunicação interprocessos podem ter impacto significante no desempenho, consumo de potência e área de memória do sistema [40]. Quando se trabalha com linguagens que usam máquinas virtuais é comum referir-se ao caso como componentes locais em máquinas virtuais diferentes. A estratégia mais adequada para realizar a comunicação nesse caso é o uso de memória compartilhada. De acordo com [41] memória compartilhada consiste na forma mais eficiente de comunicação entre processos locais. Em [40] pode-se ver uma análise de desempenho entre algumas estratégias que podem ser aplicadas nessa situação. A abordagem consiste em deixar que um processo crie um segmento de memória compartilhada e, em seguida, permita que os demais processos envolvidos na comunicação possam fazer o mapeamento dessa zona compartilhada para seus respectivos espaços de endereçamento. Assim, todos os processos podem acessar e alterar as informações compartilhadas. Essa estratégia gera problemas de condição de corrida, uma vez que temos vários processos manipulando uma zona de memória comum. Mas, para evitar estados indesejáveis, 29 as soluções podem usar semáforos para realizar a sincronização entre os processos, garantindo assim exclusão mútua no acesso. 2.7.3 Componentes em diferentes máquinas físicas Esse é o caso mais típico de comunicação em sistemas distribuídos. Nesse caso, os componentes estão localizados em máquinas físicas diferentes, sendo preciso usar uma infraestrutura de rede para fazer a comunicação entre eles. Muitas soluções empregam sistemas de middleware. Essa situação envolve vários problemas relacionados, por exemplo, com latência, jitter e confiabilidade das redes atuais. Tratar essas questões num contexto de aplicações multimídia, onde os requisitos temporais são críticos, ainda é um desafio para grande parte das pesquisas atuais. De acordo com o tipo de aplicação, deve-se escolher um protocolo de transporte adequado, que pode ser TCP, UDP, ou alguma solução variante. Para o caso de sistemas multimídia existem protocolos específicos de comunicação que fornecem informações relevantes sobre sincronização das mídias e parâmetros de rede. Nesse contexto, olhando sob o ponto de vista de uma infraestrutura de rede, requisições de uma aplicação que precise de QoS devem ser tratadas como uma solicitação que será traduzida em um contrato de serviço. Se a infraestrutura de rede não pode prover o nível de QoS necessário especificado no contrato, então a execução da aplicação pode até tornar-se inviável. Solicitações envolvem negociação dos parâmetros de QoS cujos valores devem estar bem definidos. Os principais parâmetros a serem negociados são justamente os que foram mostrados anteriormente. Nesse contexto, é necessário usar protocolos que possam balancear cada um desses parâmetros, permitindo transportar dados em tempo real mantendo certo sincronismo. Em geral, tais protocolos são construídos com base em protocolos existentes como TCP ou UDP. No caso multimídia, o TCP pode ser usado para configuração de componentes remotos, mas não para streaming devido aumento da latência e jitter [42]. Assim, pode-se usar o UDP, que é um protocolo de transporte mais simples. No entanto, ele possui algumas limitações como não permitir saber se houve perda de pacotes, nem realizar a ordenação dos pacotes no lado do receptor. As soluções exploradas atualmente consistem em encapsular na parte de dados dos pacotes UDP um pacote de protocolo de aplicação específico que permite suprir estas necessidades. Para o caso multimídia, o protocolo básico já consolidado que permite obter estas funcionalidades é o RTP (Real-time Transport Protocol). 30 3 FRAME Este capítulo apresenta o FRAME. Como discutido anteriormente, o desenvolvimento deste framework foi realizado através de um processo de reestruturação e reengenharia do Cosmos, considerando a experiência acumulada no domínio dos sistemas multimídia distribuídos para promover suporte ao desenvolvimento de sistemas autoadaptativos. Como já dito nas seções anteriores, o FRAME usa um esquema de adaptação baseado em modelos, similar a abordagem defendida em [17]. A proposta consiste em manter um ou mais modelos de representação do sistema, em tempo de execução, de modo que alguma entidade externa possa realizar uma análise desses modelos de representação identificando problemas e tentando resolvê-los. Esses modelos integram o metanível reflexivo das aplicações atuando como uma autorrepresentação do sistema. Nesse tipo de abordagem, as entidades externas que analisam o modelo executam em loop tarefas de coleta de informações, análise dessas informações, decisão com base na análise e, finalmente, execução da adaptação. Nesse sentido, FRAME usa a ideia de feedback loops apresentada em [11] para dar suporte a esse processo. Dessa forma o framework deve atender os principais requisitos, já discutidos no Capítulo 2: Identificação unívoca entre os componentes; Composição hierárquica de componentes (componentes possuem subcomponentes); Gerenciamento de ciclo de vida dos componentes; Suporte para adaptação e autoadaptação; Suporte para reflexão computacional; Suporte para streaming multimídia; Arquitetura compatível com a proposta de loops de feedback [11]; Baixos tempos para adaptação (consideraremos um tempo baixo se ele for igual ou inferior ao tempo de outras implementações para adaptação dinâmica, neste caso faremos uma comparação com o modelo de componentes Fractal [5] no Capítulo 5). Para dar suporte a esse conjunto de características o FRAME integra alguns elementos que serão apresentados a seguir, como o metamodelo proposto para o framework, sua arquitetura, uma ADL para especificação das aplicações e o modelo de componentes definido. Atualmente, há um protótipo do framework implementado na linguagem Java, cujos detalhes serão apresentados posteriormente. 31 3.1 Metamodelo do FRAME O metamodelo definido para o FRAME pode ser visto no diagrama Ecore [43] da Figura 2. Podemos destacar duas partes principais: a primeira trata da especificação estrutural do sistema e é indicada pelos elementos com cor branca; a segunda representa informações relacionadas à qualidade do serviço e ações de adaptação, sendo indicada pelos elementos com cor cinza. Figura 2 - Metamodelo do FRAME. 3.1.1 Especificação estrutural Inicialmente descreveremos o metamodelo considerando o suporte à representação estrutural do sistema, isto é, os seus componentes e os relacionamentos entre eles. O elemento Application pode ser considerado como a raiz do diagrama. Uma aplicação (Application) possui apenas um componente (Component), mas este pode conter muitos outros subcomponentes. O relacionamento parent de Component indica que todo componente é um subcomponente de outro, sendo a única exceção o componente raiz da aplicação. Os componentes possuem um conjunto de interfaces (AbstractInterface) que são especializadas para interfaces comuns (Interface), que expressam serviços providos e requeridos, e interfaces de stream (InterfaceStream), que expressam pontos de entrada e saída para o fluxo multimídia. Dessa forma, um componente possui bindings e connections, 32 respectivamente, para representar as ligações entre interfaces de serviços e interfaces de stream. Os atributos chamados name dos elementos devem identificar as entidades de maneira unívoca. Em Application, além de um nome, pode-se adicionar uma descrição (description). O atributo location de Component indica a localização do componente na rede, enquanto className referencia à implementação desse componente, por exemplo, se é usada uma linguagem orientada a objetos, será o nome da classe que deve ser instanciada. Uma interface de serviço (Interface) possui uma role que pode ser Server ou Client indicando, respectivamente, provimento ou requerimento de serviço. O atributo optional indica se a interface de serviço é obrigatória ou não. No caso de uma interface provida ser obrigatória significa que o componente é obrigado a implementar a interface, enquanto que uma interface requerida obrigatória significa que o componente não irá funcionar se a interface não for fornecida. Uma interface de stream (InterfaceStream) também possui uma role que pode ser Input ou Output, indicando a entrada ou saída de fluxo multimídia, respectivamente. Em AbstractInterface, o atributo collection indica se o componente possui apenas uma interface daquele tipo ou uma coleção de interfaces do mesmo tipo. Em Interface, signature representa o nome da interface na linguagem de programação usada para implementar o sistema, por exemplo, java.lang.Runnable para a interface Runnable da linguagem Java. Uma conexão (Connection) entre interfaces de stream Output e Input possui atributos relacionados ao streaming multimídia, como o protocolo (protocol) e porta (port) usados na comunicação, o tamanho do buffer (bufferSize) e o tempo de espera após ler de um buffer vazio (bufferTime) no receptor e o atraso mínimo (minDelay) para o envio de pacotes sucessivos pelo transmissor. AbstractInterface, Application, Component, Connection, Binding e Action (este será explicado em momento oportuno, quando discutirmos os elementos responsáveis pela especificação de QoS e autoadaptação) todos possuem propriedades (Property). Uma propriedade possui um nome (name), uma lista de valores (values) e um tipo (type) para esses valores. O tipo determina se o atributo values representa uma coleção ou um valor atômico. Por exemplo, se type é String, então values deve ser tratado como um valor atômico do tipo String. Por outro lado, se type é Integer_Collection, então values deve ser tratado como uma coleção de inteiros. As coleções representadas pelo atributo values são homogêneas em relação ao tipo. Além das propriedades, os componentes podem definir atributos (Attribute) no 33 contexto de uma interface controladora de atributos (AttributeController). Uma interface controladora de atributos encapsula um conjunto de atributos definidos para um dado componente e indica o nome da interface (signature) usada para acessar esses atributos. Um atributo herda todas as características de uma propriedade, porém é definido somente no contexto de uma interface controladora. Por exemplo, um componente codificador pode ter um atributo chamado quality que representa a qualidade do vídeo codificado. Esse componente é implementado na linguagem Java e permite acesso para esse atributo através de uma interface chamada br.encoder.IEncoder que possui métodos get e set para quality. Para esse exemplo, o componente codificador deve definir uma interface controladora com valor de signature sendo br.encoder.IEncoder e o atributo quality deve ser definido no contexto desta interface. O conceito de atributos para componentes é semelhante ao conceito de atributos para classes. Já o termo propriedade é usado aqui para representar características que não são conhecidas na fase de projeto do componente, sendo úteis para descrever características dinâmicas de plataformas específicas. Propriedades podem ser criadas no momento em que o elemento é instanciado ou durante a execução do sistema, adicionando novas características ao elemento em questão. Os atributos são os mesmos durante todo o ciclo de vida do sistema, apenas seus valores são alterados, enquanto as propriedades podem ser criadas e removidas em tempo de execução. Resumidamente, atributos são membros estáticos dos componentes, enquanto propriedades são membros dinâmicos. Um conceito semelhante de propriedades é também usado no PREMO (Presentation Environment for Multimedia Objects) [15]. 3.1.2 Especificação de QoS e autoadaptação A seguir, serão detalhados os elementos do metamodelo relacionados com a QoS do sistema e com as ações de adaptação. Conexões (Connection) e componentes (Component) podem ter várias políticas de QoS associadas (QoSPolicy), porém apenas uma delas pode estar habilitada por vez para um dado elemento. Uma política de QoS possui um atributo nome (name), que deve ser único entre as políticas definidas, um atributo que indica a frequência (frequency) de verificação das restrições (Constraint) e condições (Condition) e um atributo que diz se a política está habilitada ou não (enabled). Uma política define restrições (Constraint). Uma restrição possui um nome (name) que deve ser único entre as restrições existentes, um parâmetro (parameter) para o qual a restrição é aplicada, um valor mínimo (minValue), um valor máximo (maxValue) e um operador (operator). O operador é definido por ConstraintOperator e indica se o parâmetro 34 diminui (Decreases), aumenta (Increases), é maior que (Greater_Than), ou é menor que (Less_Than) o valor informado. Dessa forma é possível indicar faixas de valores dizendo, por exemplo, que a taxa de perda de pacotes está entre 5% e 10% (minValue=5 e maxValue=10). Também é possível indicar valores atômicos, usando a convenção de que o valor mínimo e o valor máximo são iguais, por exemplo, se a taxa de perda de pacotes aumenta 5% (minValue=maxValue=5 e operator=Increases). Quando se trabalha com faixas de valores o operador não precisa ser indicado. Restrições estabelecem regras que são testadas através de condições (Condition) definidas pela política. Condições possuem um atributo nome (name) que as identifica univocamente, além de um atributo prioridade (priority) que diz qual condição considerar no caso de mais de uma delas ser verdadeira, já que a política pode definir várias condições. Uma condição pode ser habilitada e desabilitada através do atributo enabled. No caso de estar desabilitada ela deverá ser ignorada mesmo sendo verdadeira. O predicado (predicate) da condição representa uma expressão booleana envolvendo as restrições. Por exemplo, se uma restrição, chamada R1, diz “a taxa de perda de pacotes está entre 5% e 10%” e outra restrição, chamada R2, diz “jitter aumenta 5ms”, então um predicado para uma condição C1 poderia ser R1 ^ R2, sendo “^” o AND lógico. As condições possuem ações de adaptação (Action). Quando uma determinada condição for verdadeira as ações de adaptação associadas devem ser executadas. A ação possui um alvo (target) e um valor (value). A semântica desses atributos depende do nome (name) da ação, definida por ActionType, que indica o tipo de adaptação que será executada, podendo ser: Operação de log (Log). Nesse caso o target indica o nome de um arquivo para log. O atributo value não é usado; Operações sobre atributos e propriedades dos elementos (Increase, Decrease, Multiply, Divide, Set, Add, Del). Os quatro primeiros são as operações aritméticas, por exemplo, poderíamos ter “name = Increase, target = Component:root.Component:enc.Attribute:quality, value = 5”. Isso significa aumentar em cinco, o valor do atributo quality do componente chamado enc, que é um subcomponente do componente chamado root. Set altera o valor de um atributo ou propriedade, enquanto Add e Del são usados para adicionar e remover propriedades. No caso da ação Add, o target indica o elemento que terá a propriedade e value indica o valor da propriedade. Para a ação Del, target indica a propriedade que será removida e value não é usado nesse caso. Essas ações são úteis para representar alterações nos 35 atributos e propriedades dos elementos do sistema, como os componentes, por exemplo; Operações sobre os componentes (Replace, Remove, Create). Replace diz que um componente deve ser substituído por outro; nesse caso o target indica o componente que será trocado e value indica o componente substituto. Remove retira um componente que não é mais usado do ambiente de execução do sistema; nesse caso, apenas target é usado e indica o componente que deve ser removido. Create cria um componente como um subcomponente de outro qualquer; nesse caso, o target indica o componente que irá encapsular o novo componente criado e value indica uma referência para a definição do componente que será instanciado; Operações sobre bindings e conexões (Connect, Disconnect, Bind, Unbind). No caso das ações Disconnect e Unbind o atributo value não é usado, mas target indica a conexão ou o binding que será desligado. Para as ações Bind e Connect, o target indica a interface de role Client ou Output e o value indica a interface de role Server ou Input. De acordo com a descrição do elemento Action (Figura 2), ações como Add, Connect e Create não teriam todas as suas informações expressas. Por exemplo, uma conexão possui vários atributos que devem ser configurados como o protocolo e a porta. O mesmo acontece para um componente que será instanciado e precisa informar um nome e sua localização, ou para uma nova propriedade que precisa definir seu nome e tipo. A solução consiste em permitir que ações de adaptação definam propriedades. Assim, em uma ação de conexão, por exemplo, teríamos “name = Connect, target = Component:root.Component:prod.InterfaceStream:out, Component:root.Component:cons.InterfaceStream:in”. value = Essa ação implica em conectar a interface de role Output, chamada out, do componente chamado prod, com a interface de role Input, chamada in, do componente chamado cons. Essa ação deve definir propriedades para os atributos de uma conexão, como porta, protocolo, tamanho do buffer, etc. Assim teríamos propriedades do tipo: “name=bufferSize, value=1024, type=Integer”; “name=protocol, value=RTP, type=String” e assim por diante. 3.2 Arquitetura do FRAME A arquitetura definida para o framework FRAME pode ser vista na Figura 3. 36 Figura 3 - Arquitetura do FRAME mostrando seus componentes internos. A arquitetura é formada por dois componentes maiores. O componente FrameCore engloba os principais componentes do framework, como parsers, configuradores e a implementação do metamodelo, enquanto o componente ModuleCommunication é responsável pela comunicação multimídia, ou seja, streaming. Os elementos internos de ModuleCommunication serão descritos brevemente neste trabalho, pois este módulo foi desenvolvido em trabalhos anteriores do grupo e pode ser visto com maiores detalhes em [21]. Em ModuleCommunication temos os componentes Source e Target que são, respectivamente, os pontos de origem e destino do fluxo multimídia. As interfaces ISourceModule e ITargetModule possuem, respectivamente, os métodos send e receive que permitem enviar e receber dados (bytes). Por sua vez as interfaces ISourceInfoConf e ITargetInfoConf são usadas pelo gerente da conexão (ConnectionManager) para configurar esses elementos. O ConnectionManager cria e controla monitores (Monitor e IMonitor), bem como a conexão entre Source e Target e disponibiliza métodos para obter parâmetros de QoS, como jitter, taxa de perda de pacotes e outros. O Monitor monitora a comunicação de acordo com a política definida no modelo para a conexão em questão, sendo que para isso ele acessa o SystemModel. Quando Monitor percebe algum problema ele notifica o ConnectionManager sobre o ocorrido e, este deverá executar as adaptações necessárias de acordo com as ações definidas nas políticas de QoS para a conexão em questão. Neste caso, podem ser trocados os componentes de Source e Target responsáveis pelo fluxo multimídia, por exemplo. Atualmente o ModuleCommunication fornece a troca de componentes dando suporte à mudanças das propriedades de uma conexão em tempo de execução, por exemplo, troca de protocolos de comunicação, alteração no tamanho do buffer, alteração de porta e alteração no tempo de espera após ler de um buffer vazio ou do tempo mínimo de atraso para envio de 37 pacotes. É importante ressaltar que originalmente, era suportada apenas a troca de protocolo, mas o presente trabalho estendeu a proposta incluindo essas outras possibilidades. O módulo de comunicação também possui uma estratégia para seleção de mecanismo de comunicação que permite detectar se a comunicação é local ou remota e usar o mecanismo mais eficiente, entre buffer local sincronizado, memória compartilhada e protocolos de rede, de acordo com a localização dos componentes envolvidos. Já em FrameCore, o componente SystemModel implementa as estruturas definidas pelo metamodelo e fornece uma interface (ISystemModel) para acesso aos metaelementos. Em FrameCore estão presentes os configuradores do framework. O principal deles é Configurator que possui toda a lógica para gerência do sistema, acesso ao SystemModel, criação e remoção de componentes, bem como adaptações relacionadas a serviços providos e requeridos pelos componentes do sistema. O componente MasterConfigurator é usado para disponibilizar acesso remoto ao Configurator. Existe apenas uma instância de MasterConfigurator, Configurator e SystemModel e todas devem estar no mesmo espaço de endereçamento. Nesse sentido, o componente SlaveConfigurator é usado nas máquinas remotas apenas para permitir acesso aos recursos e serviços disponibilizados nela, por exemplo, criação de novos componente remotos em uma máquina que não está rodando o MasterConfigurator. Dessa forma, todo nó da rede que executa ou irá executar um componente FRAME deve estar executando uma instância de SlaveConfigurator. O Configurator faz uso dos componentes ADL2Model e Model2ADL. O primeiro mapeia definições de uma ADL para as estruturas definidas pelo metamodelo e o segundo faz o inverso, gerando uma especificação atualizada, em alguma ADL, com base nas informações do modelo. As mensagens enviados para todos os componentes implementados usando o FRAME são interceptadas por ComponentWrapper. Este componente é constituído por um conjunto de classes que tem como função interceptar em tempo de execução os diferentes tipos de chamadas. Por exemplo, mensagens para interfaces providas são interceptadas pela classe ServiceWrapper, enquanto mensagens de adaptação são interceptadas pela classe BindingWrapper. Dessa forma pode-se verificar, por exemplo, se o componente está ativo antes de repassar a execução de uma determinada tarefa para ele. No caso de uma adaptação a chamada é interceptada e repassada para o componente ProxyController. O ProxyController usa as interfaces IConfigurator e ISystemModel para efetuar as mudanças necessárias no sistema. Dessa forma é possível para o desenvolvedor solicitar adaptações diretamente ao componente que possui o serviço em questão e a chamada 38 irá passar automaticamente ao Configurator e ao SystemModel devido o ProxyController. A interface IMasterConfigurator é disponibilizada ao ambiente externo de forma a permitir solicitações de adaptação, sendo possível, inclusive, ordenar ações de adaptação remotamente. A qualquer momento deve ser possível solicitar ao Configurator para gerar uma especificação atualizada do sistema, já que a especificação original talvez não represente a realidade atual, devido à execução de adaptações. Neste caso, Configurator irá usar Model2ADL, como citado anteriormente. A arquitetura é inspirada no esquema de adaptação baseada em modelos apresentada na Figura 1. O núcleo fixo do framework (FrameCore) não é dependente do módulo de comunicação que é um ponto flexível podendo ser usado outro módulo desde que respeite as mesmas interfaces. 3.3 Modelo de Componentes O framework FRAME fornece um modelo de componentes que tem como objetivo reduzir o esforço para projetar, implementar, implantar e reconfigurar sistemas e aplicações. Resumidamente, as principais características presentes no modelo de componentes definido são: Reflexão computacional: os componentes possuem capacidades para introspecção e intercessão; Composição hierárquica: componentes podem ser compostos por outros componentes. Isso permite também o compartilhamento de recursos, pois o mesmo componente pode ser subcomponente de vários outros; Bindings: abstração para a ligação entre os componentes, através de interfaces providas e requeridas. Podem ser alteradas em tempo de execução; Conexões: abstração para a ligação entre os componentes, através de interfaces especializadas para streaming multimídia. Podem ser alteradas em tempo de execução; Distribuição transparente: os componentes podem ser criados em contexto local ou remoto. As abstrações para bindings e conexões permitem a comunicação entre eles de forma transparente; Controle de ciclo de vida: permite que os componentes sejam iniciados ou parados. Monitores podem inspecionar o estado dos componentes durante a execução; Controle do estado: permite que o estado dos componentes seja salvo e, eventualmente, transferido para outros componentes; Capacidade de reconfiguração: o modelo deve dar suporte para reconfigurações 39 dinâmicas do sistema, tanto no sentido de adaptação, quanto de autoadaptação. Para que todas as características citadas sejam fornecidas é necessário que os componentes do sistema implementem um conjunto de interfaces, permitindo à aplicação e ao próprio framework fazerem uso dessas funcionalidades. Dessa forma destacamos os tipos de interfaces controladoras que podem ser fornecidas por tais componentes: 1. Interface controladora de atributos (IAttributeController); 2. Interface controladora de bindings (IBindingController); 3. Interface controladora de conexões (IConnectionController); 4. Interface controladora de ciclo de vida (ILifeCycleController); 5. Interface controladora de componentes (IComponentController); O primeiro tipo de interface (IAttributeController) deve ser implementado sempre que o componente desejar fornecer métodos de acesso (get e set) para seus atributos. Para isso deve ser definida uma interface específica para o componente em questão com os métodos get e set necessários. Essa interface deve estender IAttributeController indicando que ela é uma interface controladora de atributos. O segundo tipo de interface (IBindingController) permite alterar em tempo de execução os bindings entre os componentes do sistema. As dependências de um componente são expressas através de suas interfaces requeridas, então o componente deve fornecer a interface controladora de bindings sempre que for desejável alterar suas dependências em tempo de execução, ou seja, alterar as referências que fornecem os serviços requeridos por suas interfaces de role Client. O terceiro tipo de interface (IConnectionController) é semelhante ao anterior (IBindingController), porém são interfaces que atuam nas conexões dos componentes e não nos bindings. Através dela é possível alterar não apenas as conexões entre interfaces de stream Input e Output, mas também as propriedades da conexão, como protocolo, tamanho de buffer, porta de comunicação, etc. O quarto tipo de interface (ILifeCycleController) permite descobrir informações sobre o estado de execução do componente, bem como alterá-lo quando for conveniente. Assim, é possível parar apenas os elementos realmente necessários quando uma adaptação dinâmica precisa ser executada. Por exemplo, antes de desfazer um bind é preciso parar o componente afetado, atualizar a referência da sua interface cliente em questão e, em seguida, iniciar novamente o componente afetado. Uma observação importante deve ser feita sobre a interface IAttributeController. Através dela é possível salvar o estado dos componentes, bem como transferi-lo para outros 40 componentes. Para isso as operações de leitura dos atributos devem continuar disponíveis mesmo quando o componente é parado via ILifeCycleController. Isso é necessário quando um componente stateful é trocado por outro. Nesse caso, o estado do componente é importante para o sistema continuar a executar corretamente. Dessa forma, deve-se recuperar o estado do componente antigo e transferi-lo para o novo componente. Essa transferência não é feita automaticamente pelo framework. O estado deve ser recuperado e transferido, respectivamente, através dos métodos get e set da interface definida como controladora de atributos. O quinto e último tipo de interface controladora (IComponentController) permite acessar um determinado componente, bem como as informações de seus metadados. Dessa forma é possível, por exemplo, acessar suas interfaces ou descobrir qual seu supercomponente (o componente que encapsula um subcomponente). Na verdade esta interface não é implementada diretamente pelos componentes do sistema. O que acontece é que cada componente, juntamente com sua descrição (elemento do metanível), é encapsulado automaticamente pelo framework em uma instância de uma classe chamada FrameComponent, sendo esta a classe que implementa IComponentController. Além das interfaces citadas, o modelo de componentes define interfaces para cada um dos tipos apresentadas no metamodelo proposto como Component, InterfaceStream, QoSPolicy, Action e outros. A aplicação pode fazer uso dessas interfaces para realizar certas alterações e consultas no metanível (introspecção e intercessão). Adaptações relacionadas às políticas de QoS (QoSPolicy) e às propriedades (Property) dos elementos devem ser feitas diretamente através dessas interfaces. Por questões de segurança e simplicidade na distribuição dos componentes, apenas componentes em mesmo espaço de endereçamento do SystemModel e do Configurator podem realizar esse tipo de alteração. Na Figura 4, podem-se ver as interfaces e classes usadas para construir uma aplicação. Entre elas, estão as interfaces controladoras apresentadas. Um componente FRAME deve pelo menos estender a classe abstrata BasicFrameComponent e implementar a interface IBasicFrameInterface. Todas as demais interfaces devem ser usadas caso o componente precise fornecer funcionalidades específicas. Por exemplo, se um componente A usa um serviço de um componente B, mas eventualmente ele pode passar a usar esse serviço de um componente C, ou seja, se ele deseja trocar em tempo de execução um de seus componentes provedores, ele deve implementar a interface IBindingController. 41 Figura 4 - Diagrama de classes para o modelo de componentes definido no FRAME. Como o protótipo do framework foi implementado na linguagem Java, decidiu-se usar RMI para realizar a distribuição dos componentes. Por causa disso, podemos ver que as interfaces controladoras e IBasicFrameInterface estendem java.rmi.Remote, bem como BasicFrameComponent estende java.rmi.server.UnicastRemoteObject. Outra implicação disso é que as classes que implementam os elementos do metamodelo realizam a interface IFrameSerializable que estende java.oi.Serializable e org.eclipse.emf.ecore.EObject. A primeira é necessária, pois os objetos enviados pelo RMI devem ser serializáveis e a segunda também já que as classes do modelo são geradas automaticamente pelo EMF (Eclipse Modeling Framewok) [44] e é requisito realizar esta interface, o que traz algumas vantagens como a validação das aplicações montadas de acordo com o metamodelo. Como esperado, a interface IBindingController possui métodos bind e unbind para permitir ligar e desligar componentes, enquanto que IConnectionController possui operações connect e disconnect, relacionadas à uma conexão. ILifeCycleController possui métodos para iniciar (start), parar (stop) e verificar se o componente está ativo (isAlive). IComponentController permite à aplicação obter a referência de um componente que fornece um determinado serviço através da operação queryInterface. As demais operações disponibilizam as interfaces controladoras para o componente em questão. A operação getComponent retorna um Component (mesmo tipo Component do metamodelo) que representa os metadados do elemento. Tanto a aplicação quando o framework usam o conjunto de interfaces do modelo de 42 componentes para realizar o gerenciamento e uso dos componentes do sistema. A aplicação irá usá-las de acordo com sua necessidade. A Figura 5 mostra a forma como o framework interage com essas interfaces. As interfaces controladoras de atributos, conexões e bindings serão usadas pelo SystemModel sempre que for necessário instanciar novos componentes, enquanto ComponentWrapper, além das mesmas interfaces usadas pelo SystemModel, também fará uso de ILifeCycleController para consultar o status dos componentes e das interfaces de negócio dos componentes. ComponentWrapper possui classes internas responsáveis por interceptar mensagens para os diferentes tipos de interfaces dos componentes do sistema, sendo AttributeWrapper, SeviceWrapper e BindingWrapper. A classe FrameComponent encapsula uma referência para a instância do componente do sistema (IBasicFrameInterface) e uma referência para os metadados desse componente (Component do metamodelo) mantendo uma associação entre eles. Através de IComponentController são disponibilizadas as interfaces de negócio e as interfaces de controle do componente para a aplicação. Figura 5 - Componentes arquiteturais e interfaces do modelo de componentes. 3.4 Estratégia de Autoadaptação O framework FRAME explora o conceito de feedback loops [11] para dar suporte ao processo de autoadaptação. Essa abordagem permite focar o problema de maneira sistemática e bem organizada. Feedback loops provém um mecanismo genérico para autoadaptação. Eles geralmente envolvem quatro atividades chaves: coleta, análise, decisão e ação. O loop executado em 43 torno dessas atividades é mostrado na Figura 6. Figura 6 - Atividades do loop de controle, adaptado de [45]. A primeira atividade consiste em coletar informações. Nesse momento o framework coleta dados do modelo mantido em tempo de execução. Os dados coletados são em seguida analisados pela segunda atividade do loop. Essas duas primeiras atividades do loop são executadas no FRAME pelos monitores (Monitor da Figura 3). Eles são responsáveis por coletar as informações de QoS e analisá-las com base nas informações das políticas de QoS presentes no modelo de representação sistema. A análise é feita através da comparação dos valores de parâmetros definidos pela política com os valores atuais obtidos pelos monitores. Se essa comparação detectar a necessidade de uma adaptação, por exemplo, devido alguma das condições definidas na política de QoS ser verdadeira, então o Monitor envia uma notificação ao gerente da comunicação (ConnectionManager) sobre a atual situação. Cabe ao ConnectionManager juntamente com o Configurator executar a terceira atividade do loop e tomar a decisão do que será feito com base nas informações sobre as ações de adaptação definidas no modelo. Para alterações realizadas no streaming multimídia o próprio gerente da conexão é capaz de decidir o que e como fazer, porém se alguma das ações corretivas requer adição ou remoção de componentes para provimento de novos serviços ou troca dos serviços antigos, então o Configurator será invocado. E, finalmente, um desses dois elementos irá executar a quarta e última atividade do loop de controle que é colocar a adaptação em ação, ou seja, efetuar as mudanças atualizando o modelo de representação e o sistema base. Depois que as quatro atividades forem executadas o processo reinicia pela primeira atividade (coleta). Obviamente, nem todas as tarefas desse loop de controle são sempre executadas. As únicas obrigatoriamente executadas em cada loop são a coleta e a análise. Se a análise das informações coletadas não detectar que existe necessidade de adaptação, então o loop pula as atividades de decisão e ação, reiniciando na coleta novamente. Atualmente, o protótipo implementado do framework permite adaptação relacionada 44 aos serviços dos componentes, ao streaming multimídia e às políticas de QoS. No primeiro caso, desde que não sejam componentes participantes de um streaming, é possível trocar livremente os componentes. No caso das políticas, basta que as informações presentes no modelo mantido em execução sejam alteradas. No caso de adaptação dos componentes envolvidos em um streaming multimídia, a tarefa é mais complicada, pois existe um fluxo contínuo de dados que não deveria ser interrompido. Neste caso, as adaptações são feitas através de mudanças nas propriedades da conexão e o ConnectionManager do módulo de comunicação decide se a mudança necessita ou não de uma troca de componentes. O diagrama mostrado na Figura 7 apresenta a sequência de chamadas para realizar a troca de um componente provedor de determinado serviço, obviamente, respeitando as suas interfaces providas e requeridas. Neste caso, a origem da solicitação poderia, por exemplo, partir da aplicação (um cliente qualquer). As etapas incluem a criação do novo componente, parar a execução do componente afetado, fazer o unbind para o antigo, em seguida o bind para o novo e, finalmente, reiniciar o componente afetado. 45 Figura 7 - Diagrama de sequência mostrado os passos para trocar um componente. A criação de um novo componente é solicitada ao Configurator, que repassa a chamada ao SystemModel. Este cria e registra os componentes em um índice para uso posterior e também realiza as atualizações necessárias no modelo. Em seguida deve-se fazer o unbind do componente antigo. Para um cliente que usa essa operação, ela é feita como se fosse enviada diretamente para o componente afetado, no entanto, a chamada é desviada para um elemento chamado BindingWrapper, que intercepta a mensagem para o ProxyController, como dito anteriormente. ProxyController realiza as atualizações devidas no modelo em tempo de execução e, em seguida, o BindingWrapper libera a chamada para seguir com sua execução, chegando a mensagem unbind no componente em questão. Após o componente ser 46 desligado solicita-se ao Configurator para removê-lo, mas note que isso é necessário apenas se não queremos mais esse componente no ambiente de execução. Finalmente, realiza-se o bind para o novo componente. A operação bind segue passos semelhantes à operação unbind explicada acima. Após todas as etapas o componente pode ser reiniciado. Obviamente, o controle das dependências é feito pelo framework. Quando um componente é removido, por exemplo, seus subcomponentes e todas as suas dependências também são removidas. As mensagens enviadas aos componentes são interceptadas, o que torna possível verificar se o componente está apto para recebê-la. Se ele não estiver ativo a mensagem será interrompida. A adaptação apresentada acima permite trocar os componentes do sistema respeitando as suas interfaces providas e requeridas. Por outro lado, quando se deseja realizar a adaptação de um streaming, a tarefa é realizada pelo componente ModuleCommunication, apresentado anteriormente na arquitetura do FRAME. Esse módulo de comunicação foi desenvolvido em trabalhos anteriores do grupo. Ele suporta a seleção de mecanismos de comunicação eficientes de acordo com a localização dos componentes, bem como adaptações como troca de protocolo de comunicação, mudança de tamanho de buffer de recepção, alteração da porta de comunicação e outros parâmetros de uma conexão multimídia. Aqui apresentaremos apenas as principais funções do módulo. Uma descrição mais detalhada pode ser encontrada em [21]. O diagrama da Figura 8 mostra a troca dos elementos que efetivam a comunicação multimídia. No módulo, esses elementos são representados por um SourceCommunicator e um TargetCommunicator, sendo esse processo controlado pelo ConnectionManager. Um exemplo dessa situação seria a troca do protocolo de comunicação usado no streaming. 47 Figura 8 - Processo de adaptação para streaming multimídia. É importante destacar duas etapas no processo: preparação e atualização de referências. Na primeira etapa ocorre a criação de novos componentes que sejam capazes de trabalhar com o protocolo alvo. Essa etapa é iniciada com o envio da mensagem prepareAdaptation para o Source e para o Target. Isso cria novos componentes com suporte para as novas características da conexão e os deixam prontos para iniciar uma comunicação. Deve-se destacar que o novo receptor já deverá estar escutando em uma determinada porta esperando por dados. Na próxima etapa ocorre a atualização das referências, com descarte dos componentes antigos (mensagem updateReference). Primeiro, o ConnectionManager requisita o descarte e troca para o componente Source. Então a comunicação é fechada (close) do lado do Source. Nesse momento, o envio de dados com as características antigas é encerrado, e em seguida o componente transmissor é trocado (swap). Após a mensagem swap o novo transmissor já estará enviando dados de acordo com as novas exigências da transmissão. Note que do outro lado já existe um receptor esperando por estes dados, criado na fase de preparação, que irá armazenar os dados recebidos em buffer, até que o antigo receptor seja descartado. A mensagem updateReference para o Target tem significado diferente do apresentado 48 para o Source. No Target ela tem como função apenas notificar ao receptor que está tudo pronto para a troca do componente receptor, ou seja, o transmissor já foi trocado. O Target continuará normalmente tentando receber dados usando o método receive (a Figura 8 ilustra apenas uma chamada receive). Em certo momento, uma vez que não chegam mais dados para o componente antigo, o buffer do receptor estará vazio, e, como Target recebeu a notificação para adaptar, isso será interpretado como o momento de realizar a troca do receptor. Então, ao executar receive e encontrar um buffer vazio, o Target será notificado e fechará o receptor antigo (close), executando em seguida a troca do componente (swap). Os bytes passam então a serem recuperados no novo componente receptor que provavelmente já tem dados em buffer. Finalmente, o processo de adaptação é finalizado com a atualização do SystemModel (updateSystemModel). Com relação ao módulo de comunicação, o trabalho inicial apresentado em [21] realizava apenas a troca do protocolo de comunicação. O presente trabalho generalizou essa abordagem e fez as modificações necessárias para que a adaptação de streaming abrangesse outras características de uma conexão, como a troca da porta de comunicação, alteração do tempo atraso mínimo para envio de pacotes, mudança do tamanho do buffer, alteração do tempo de espera após ler de um buffer vazio e alterar os protocolos de comunicação, que foi mantida. 3.5 ADL A ADL é proposta pelo framework para facilitar a especificação das aplicações. Ela é baseada em XML e permite especificar os componentes do sistema, bem como os relacionamentos entre eles, as políticas de QoS e as ações de adaptação mostradas no metamodelo proposto. É importante deixar claro que o framework proposto é independente da ADL usada. Para isso, basta que seja fornecido um parser capaz de mapear a descrição da ADL para as estruturas definidas pelo metamodelo usado, neste caso um novo componente ADL2Model. O framework é completamente funcional sem a ADL. Ela foi definida apenas para facilitar a especificação da aplicação pelo desenvolvedor. O FRAME manipula internamente apenas as estruturas definidas pelo metamodelo que armazenam os metadados dos elementos, dessa forma, a ADL serve apenas como uma fonte inicial de informação que será mapeada para essas estruturas, as quais serão, posteriormente, manipuladas pelo FRAME. A Figura 9 mostra a definição de um componente exemplo com suas interfaces, atributos e propriedades. A definição possui um atributo name com valor component_definition_name que deve ser o mesmo nome do arquivo XML, permitindo ao 49 parser ser capaz de referenciar os arquivos XML a partir dos nomes das definições. Um atributo class indica o nome da classe que deve ser instanciada para se fazer uso desse componente. Figura 9 - Componente definido na ADL proposta. No exemplo, os atributos do componente são definidos dentro do contexto de uma interface controladora de atributos. Os atributos são definidos através de um nome, valor e tipo. O tipo pode ser qualquer um dos indicados no metamodelo (Figura 2) na enumeração ValueType. Os atributos são agrupados no contexto de uma interface controladora que é indicada por signature da tag AttributeController. O valor de signature é o nome completo da interface, na linguagem de programação usada, que possui os métodos set e get dos atributos definidos. Os nomes dos métodos de acesso na interface informada devem seguir a convenção padrão, ou seja, get ou set seguido do nome do atributo com a primeira letra maiúscula. O componente também pode especificar suas propriedades através da tag Property. O exemplo da Figura 9 apresenta duas propriedades. Definir uma propriedade é semelhante a definir um atributo, sendo preciso indicar o nome, o valor e o tipo, porém propriedades não são agrupadas por uma interface controladora. Ainda na Figura 9, são definidas duas interfaces para serviços, chamadas ic e is, com roles Cliente e Server, respectivamente. O atributo role de Interface pode assumir os valores Client e Server indicando, respectivamente, que a interface é requerida ou provida. O atributo signature indica o nome completo dessa interface na linguagem de programação usada para implementar o sistema, enquanto o atributo optional é um booleano que indica se a interface é opcional. Relembrando, uma interface provida, definida como opcional, significa que o 50 componente não é obrigado a fornecê-la, enquanto uma interface requerida, definida como opcional, significa que o componente pode funcionar mesmo que ela não seja fornecida. O atributo collection de Interface é um booleano que indica se o componente possui uma coleção dessa interface, sendo true nesse caso, ou false caso contrário. Também são definidas duas interfaces para stream chamadas out e in, com roles Output e Input, respectivamente. O atributo role de InterfaceStream pode assumir os valores Output e Input indicando, respectivamente, pontos de entrada e saída de fluxo de dados, enquanto collection é um booleano que indica se o componente possui uma coleção dessa interface, sendo true nesse caso, ou false caso contrário. Como dito anteriormente, um componente pode conter outros componentes. O exemplo da Figura 10 mostra uma definição de componente chamada component_definition_root que encapsula a definição do exemplo mostrado anteriormente na Figura 9. Adicionalmente, na Figura 10, podemos ver que um componente pode ser criado referenciando-se uma definição externa ou diretamente dentro da tag Component. Figura 10 - Exemplo da definição de um componente composto. Na Figura 10, o componente chamado cname1 segue a definição de component_definition_name. Vários componentes podem ser criados com base em uma definição. Já o componente chamado cname2 é definido diretamente dentro do componente raiz. Usar uma definição externa melhora a legibilidade e o reuso de código da especificação. Adicionalmente, a tag Component possui um atributo location que indica justamente a localização onde está instância será criada na rede. É importante deixar clara a diferença entre a tag ComponentDefinition e Component. A primeira é usada para criar definições de componentes, enquanto a segunda é usada para 51 instanciar uma definição. Podemos fazer uma analogia com o conceito de classe e objeto da orientação a objetos, no sentido que um objeto é uma instância de um modelo que é a classe. Aqui uma definição de componente funciona como esse modelo. Caso o componente use uma definição externa através do atributo definition, o atributo class deve ser informado apenas na definição externa na tag ComponentDefinition. Ainda sobre a Figura 10, na parte inferior temos a realização de um binding entre a interface requerida ic do componente cname2 e a interface provida is do componente cname1. Finalmente, após o binding, temos a realização de uma conexão com source sendo a interface de stream chamada out do componente cname1 e o target sendo a interface de stream chamada in do componente cname2. O protocolo usado nesse streaming é UDP, na porta 8888, com buffer de recepção de 1024 bytes, espera após ler de um buffer vazio de 2000ms e atraso entre envios de pacotes sucessivos no transmissor de dois milissegundos. Além dos componentes e seus relacionamentos, a aplicação precisa especificar as políticas de QoS e regras de adaptação como definidas no metamodelo. A Figura 11 mostra um exemplo completo usando a ADL proposta. É importante notar que a aplicação define apenas um componente raiz e todos os outros devem ser subcomponentes dele, em conformidade com o metamodelo proposto. Figura 11 - Exemplo completo de aplicação usando a ADL proposta. Na Figura 11, podemos ver a aplicação com seu componente raiz, que segue a definição mostrada no exemplo anterior, e uma política de QoS, chamada qos-policy, que possui como alvo (target) a conexão chamada conn que está encapsulada no componente root. A frequência de teste das restrições e condições especificadas na política é definida em milissegundos pelo atributo frequency e ela pode ser habilitada ou desabilitada pelo atributo 52 booleano enabled. O atributo targetType indica o tipo do alvo da política. O alvo de uma política define seu ponto de atuação e de acordo com o metamodelo apenas conexões e componentes definem políticas de QoS, o que implica que o alvo de uma política deve ser, ou um componente, ou uma conexão. A decisão de definir as políticas diretamente dentro da tag Application e referenciar um alvo a partir delas, ao invés de defini-las dentro da tag Connection ou Component correspondente, foi tomada visando aumentar separação entre definições estruturais e requisitos de QoS. Restrições podem ser expressas pela tag Constraint. No exemplo da Figura 11, existe uma restrição c1 associada à taxa de perda de pacotes da conexão alvo que diz: “a taxa de perda de pacotes diminui em duas unidades”. As restrições são usadas como predicados de condições, assim a tag Condition representa nesse exemplo uma condição chamada condition1, com prioridade um e ativa, cujo predicado é acontecer c1. Quando o predicado da condição é satisfeito, uma ou mais ações de adaptação são executadas. Ações são especificadas pela tag Action. O atributo name de Action indica qual o tipo da ação, podendo ser qualquer um dos definidos na enumeração ActionType, como mostrado no metamodelo. A função dos atributos target e value varia de acordo com o tipo de ação escolhido, como foi explicado anteriormente. 3.6 Protótipo Implementado Conceitualmente, o FRAME integra todas as funcionalidades e características que foram apresentadas para ele neste trabalho. Atualmente, há uma implementação de um protótipo feita para verificar a viabilidade do framework na prática e que abrange as principais características apresentadas. Resumidamente, dos principais requisitos apresentados, o protótipo contemplou: Identificação unívoca entre os componentes: garantida por restrições adicionadas ao metamodelo; Reflexão computacional: os componentes possuem capacidades para introspecção e intercessão, porém por questões de segurança a intercessão é possível desde que realizada no mesmo espaço de endereçamento do SystemModel, ou seja, através de referências locais; Composição hierárquica: componentes podem ser compostos por outros componentes; Suporte para adaptação e autoadaptação: as principais situações, já que o protótipo ainda não permite trocar livremente componentes envolvidos em streaming; Distribuição transparente: os componentes podem ser criados em contexto local ou 53 remoto. As abstrações para bindings e conexões permitem a comunicação entre eles de forma transparente; Controle de ciclo de vida: permite que os componentes sejam iniciados ou parados; Controle do estado: permite que o estado dos componentes seja salvo e, eventualmente, transferido para outros componentes. Isso é possível através das interfaces controladoras de atributo (IAttributeController); Concepção da ADL e do metamodelo; Como podemos observar a maioria das características foram contempladas pelo protótipo. Porém, como esperado, alguns pontos foram simplificados e, por isso, foram apenas parcialmente implementados, sendo eles: Atualmente o alvo de uma política de QoS pode ser apenas uma conexão. O componente Monitor ainda não contempla o monitoramento de atributos ou propriedades dos componentes. Para isso seria preciso verificar como as ações de adaptação seriam compatibilizadas com esses novos elementos; A interface IConnectionController que possui as operações connect e disconnect é usada apenas no momento da implantação do sistema, não sendo possível a aplicação conectar e desconectar livremente componentes através de suas interfaces de stream da mesma forma como faz com suas interfaces de serviços (providas e requeridas). Atualmente as adaptações de streaming estão restritas as alterações de propriedades da conexão, cabendo ao módulo de comunicação decidir se a alteração irá implicar em troca de componentes ou apenas atualização de atributos dos componentes. Atualmente, apenas a ação de adaptação do tipo Set pode ser usada via ADL, o que também impede o uso dos scripts de adaptação via ADL. Outro ponto sobre a ADL é que atualmente interfaces não podem representar coleções (atributo collection de AbstractInterface como true); 54 4 EXEMPLOS DE INSTANCIAÇÃO Neste capítulo, serão apresentados alguns exemplos de instanciação do framework buscando exemplificar a proposta. Para isso, foram definidos alguns estudos de caso com objetivos específicos que serão mostrados a seguir. 4.1 Modelando Uma Aplicação com a ADL Proposta O primeiro exemplo de instanciação apresenta a modelagem de uma aplicação para streaming de vídeo entre um codificador e um decodificador, de acordo com a abordagem apresentada por este trabalho. O objetivo é mostrar como uma aplicação pode ser especificada e também discutir alguns pontos que são fundamentais para o processo de desenvolvimento de uma aplicação, destacando principalmente o uso da ADL. A modelagem considera o uso da linguagem Java para implementação desse estudo de caso. Mas é importante frisar que para este exemplo não foi gerada uma implementação na linguagem Java, como dito anteriormente o objetivo é apenas mostrar a modelagem de uma aplicação completa usando a ADL proposta. A aplicação modelada nesse estudo de caso é formada por um componente principal, composto de dois outros componentes, sendo um codificador, responsável por codificar e enviar o fluxo de vídeo, e um decodificador, que recebe o fluxo e decodifica-o. Na ADL proposta, os componentes da aplicação podem ser definidos no arquivo XML da aplicação ou em arquivos separados, como mostrado anteriormente. O atributo chamado definition na tag Component é usado para referenciar definições externas de componentes, como mostrado na declaração do componente encoder na Figura 12. 55 Figura 12 - Uma aplicação definida com a ADL proposta. Na Figura 12, pode-se ver um componente chamado root que contém dois outros componentes chamados encoder e decoder, localizados em máquinas com endereços IP diferentes (location). O componente encoder segue a definição especificada em adl.EncoderADL, enquanto o componente decoder define diretamente sua própria especificação. A definição adl.EncoderADL pode ser vista na Figura 13. Dessa forma, encoder possui uma interface de stream com role Output chamada out, enquanto decoder possui uma interface de stream com role Input chamada in. O atributo class indica o nome da classe, já que estamos considerando a linguagem Java nesse exemplo, que deve ser instanciada para 56 fazer uso do componente, sendo mapeado para o atributo className de Component como definido no metamodelo. Figura 13 - Definição adl.EncoderADL. O componente encoder possui dois atributos, um inteiro com valor 90, chamado quality, que representa a porcentagem da qualidade do vídeo codificado e uma String, com valor h264, chamada media-type, que indica a codificação usada. Esses atributos são acessados através de uma interface controladora de atributos com assinatura example.IEncoderAttController. Note que este será o valor mapeado para o atributo signature de AttributeController, como indicado no metamodelo. O componente decoder define apenas um atributo do tipo string, chamado media-type, com valor também h264 indicando o tipo de codificação suportada. Esse atributo é definido no contexto de uma interface controladora com assinatura example.IDecoderAttController. Novamente, este será o valor mapeado para signature do elemento AttributeController definido no metamodelo. No final da definição do componente root (Figura 12) podemos ver a conexão entre os dois subcomponentes definidos, tendo como origem a interface chamada out do encoder e como alvo a interface chamada in do decoder. Adicionalmente, na tag Connection são configurados os demais atributos da conexão como o protocolo, a porta, o tamanho do buffer, etc. O último passo consiste em definir as políticas de QoS com suas restrições, condições e respectivas ações de adaptação. Na Figura 12, temos uma política chamada qos-policy que tem como alvo a conexão chamada conn estabelecida entre o codificador e o decodificador. A política do exemplo define duas restrições chamadas c1 e c2. A primeira será satisfeita quando a taxa de perda de pacotes aumenta em duas unidades e a segunda quando o RTT (Round-Trip Time) for maior que 100. Na prática, isso representa 2% e 100ms, pois a taxa de perda de pacotes é dada em porcentagem e o RTT em milissegundos. Ainda na Figura 12, as restrições são usadas em condições (condition-1 e condition-2). O predicado da primeira é um simples OR lógico (c1 | c2), enquanto a segunda diz se não acontecer c1 e não acontecer c2 (!c1 ^ !c2). Uma vez que o predicado seja verdadeiro e o 57 atributo enabled indique true, as ações de adaptação correspondentes são executadas. A ação de condition-1 diminui a qualidade da codificação do vídeo em duas unidades, enquanto a ação de condition-2 aumenta a qualidade em duas unidades. Na prática isso representa diminuir ou aumentar a qualidade em 2%, pois quality é dado em porcentagem. Considerando a arquitetura proposta anteriormente, é possível submeter remotamente ao Configurator um conjunto de ações de adaptação. Por exemplo, poderíamos usar uma versão gratuita, ou mais barata, do decodificador, bastando ordenar a troca desse componente. Um script de adaptação para a aplicação example, desse estudo de caso, é ilustrado na Figura 14. Figura 14 - Script com ações para adaptação. A primeira ação desse script determina a criação de um componente (name=create) como subcomponente do componente root (target=Component:root). Esse componente segue a especificação definida em adl.FreeDecoderADL (value=adl.FreeDecoderADL) que pode ser vista na Figura 15. Essa instância possui nome free-decoder e localização 192.168.0.3, ambos definidos usando propriedades. A segunda ação consiste em substituir o subcomponente de root chamado decoder pelo novo componente chamado free-decoder. Figura 15 - Definição adl.FreeDecoderADL. O Configurator deve encarregar-se de executar as adaptações, realizando as alterações necessárias de acordo com o tipo de ação solicitada. Por exemplo, em um replace ele irá desconectar todas as conexões e bindings do componente alvo, conectá-las ao novo componente e finalmente remover o componente antigo do ambiente de execução. Note que para manter a consistência do sistema, no caso da remoção de um componente, por exemplo, todos os seus subcomponentes são também removidos, bem como 58 as políticas de QoS definidas para eles. Assim, além de ações, o script também pode definir novas políticas de QoS para os novos elementos, usando exatamente a mesma sintaxe do exemplo da Figura 12. Novamente, vale ressaltar que este estudo de caso não foi implementado, mas apenas modelado na ADL, e, atualmente, por causa das limitações apresentadas anteriormente algumas das características mostradas não são contempladas pelo protótipo, como é o caso dos scripts de adaptação. 4.2 Abordagem Puramente Java Para a Criação de Aplicações A ideia é demonstrar através de um estudo de caso como fazer uso do FRAME, criando uma aplicação sem a ADL, usando apenas o framework implementado na linguagem Java. O estudo de caso é uma aplicação com um único componente que implementa uma simples calculadora com as quatro operações aritméticas básicas. A classe Java e sua interface são mostradas respectivamente na Figura 16 e na Figura 17. A aplicação é simples, já que a ideia é mostrar como construir os componentes com o FRAME, e não elaborar uma aplicação complexa. Figura 16 - Classe Calculator. Figura 17 - Interface ICalculator. Basicamente temos a classe Java (Calculator) que estende BasicFrameComponent e fornece a interface (ICalculator), sendo que esta estende IBasicFrameInterface. O diferencial está na forma como essa classe será instanciada e manipulada pelo framework. Essa 59 instanciação não será feita diretamente pela aplicação, mas sim pelo framework que irá manter a associação entre essa instância e sua descrição no metanível, especificado pelo metamodelo proposto. Dessa forma, deve-se primeiramente construir a descrição da aplicação usando os elementos definidos no metamodelo. Para isso usa-se uma fábrica para a criação desses elementos como mostrado na Figura 18. Figura 18 - Criando a descrição da aplicação diretamente com a fábrica do framework. Nem todos os atributos de cada elemento precisam ser especificados, pois alguns deles assumem valores default, como é o caso do atributo location de Component que possui valor default “127.0.0.1”. No exemplo é criada uma aplicação (Application) com nome calculator, um componente chamado root que tem como atributo className o nome da classe Calculator vista na Figura 16 e uma interface de role Server com nome iface_calc que tem como valor do atributo signature o nome da interface ICalculator vista na Figura 17. 60 A seguir, ainda na Figura 18, a interface criada é adicionada para o componente root e logo em seguida, este é configurado como componente raiz da aplicação. Finalmente, a última linha não é obrigatória, mas foi adicionada para mostrar como é possível verificar se a descrição montada é válida, ou seja, está realmente em conformidade com o metamodelo. Por exemplo, o nome de um componente é obrigatório e deve sempre ser informado, então, caso isso não seja feito a validação irá retornar false, porém nosso exemplo é válido e o retorno é true. Uma vez que a descrição da aplicação esteja pronta, ela deve ser carregada pelo Configurator. Isso fará com que a descrição seja adicionada para o SystemModel e que os componentes definidos sejam finalmente instanciados. Depois que a descrição for carregada pelo Configurator todo acesso aos elementos deve ser feito via interface ISystemModel. Essas etapas são mostradas na primeira metade da Figura 19. O método loadNewApplication presente na interface IMasterConfigurator possui duas formas: a primeira recebe um Application como parâmetro e a segunda recebe um arquivo XML com a descrição da aplicação escrita na ADL apresentada anteriormente. Figura 19 - Carregando a descrição e recuperando referências para o componente. Uma vez que a descrição esteja carregada podemos recuperar um componente FRAME acessado via IComponentController que mantém a associação entre a instância da classe Calculator e sua representação descrita por um elemento do tipo Component. Para isso usamos o método queryFrameComponent, presente na interface ISystemModel, que dado o nome do componente retorna uma referência do tipo IComponentController, sendo neste caso 61 o componente nomeado anteriormente de root. Uma vez obtida essa referência, podemos usar o método queryInterface, disponível em IComponentController, para recuperarmos referências para interfaces específicas do componente e assim fazer uso de seus serviços, como indicado também na Figura 19. Por fim, após definir a descrição puramente na linguagem Java, sem ADL, uma coisa interessante que pode ser feita é solicitar ao Configurator para gerar essa descrição na ADL proposta. Isso pode ser feito de maneira muito simples como está indicado na Figura 20. A saída por sua vez é mostrada na Figura 21. Nesse caso, o Configurator usa o componente Model2ADL, via interface IModel2ADL, que realiza esse mapeamento. Figura 20 - Mapeamento do modelo para a ADL. Figura 21 - Descrição gerada pelo mapeamento feito pelo componente Model2ADL. 4.3 Aplicações Adaptativas e Autoadaptativas Este é o terceiro e último estudo de caso apresentado pelo trabalho. A aplicação que será mostrada a seguir é mais complexa do que a anterior desenvolvida usando apenas interfaces Java que são disponibilizadas pelo framework. Esse aumento de complexidade se deve ao aumento do número de componentes e ao uso de características adaptativas e autoadaptativas. Dessa forma, seria muito mais complicado implementar usando apenas as interfaces Java disponibilizadas pelo framework, portanto, neste estudo de caso, usaremos a ADL. Basicamente, a aplicação apresentada tem como objetivo verificar a viabilidade do framework em um cenário com possibilidade de adaptação envolvendo tanto componentes multimídia (que manipulam fluxo contínuo de dados através de uma InterfaceStream), quanto componentes que possuem apenas interfaces de serviços, providas ou requeridas. A ideia da aplicação é que existe um servidor e um cliente. O cliente assiste a um vídeo disponibilizado pelo servidor e pode enviar comentários sobre o filme em exibição. Toda comunicação entre cliente e servidor, exceto o streaming multimídia, é criptografada. 62 Esse cenário permite realizar adaptações trocando o componente de criptografia usado pelo cliente e pelo servidor, como também permite realizar as adaptações na comunicação multimídia, por exemplo, troca dinâmica do protocolo de comunicação, como citado anteriormente. As figuras a seguir mostram a especificação da aplicação. A Figura 22 apresenta a primeira parte da especificação para a aplicação chamada CaseStudy. A aplicação possui um componente raiz (root), como toda aplicação FRAME. Em seguida temos a declaração de um componente chamado crypt que usa uma definição externa (adl.cs_crypt_hex). Este é o componente responsável pela criptografia e será compartilhado entre cliente e servidor. Figura 22 - Especificação do estudo de caso (parte um). Ainda sobre a Figura 22, após a declaração de crypt temos a declaração e definição do componente chamado Client, que tem como classe Java application.cs.Client. O cliente possui duas interfaces: a primeira chamada iclient, que representa a interface Java application.cs.IService e indica um serviço requerido (role=Client); e a segunda chamada icrypt_clt que também indica um serviço requerido (role=Client) e representa a interface Java application.cs.ICrypt. Internamente ao cliente, temos a definição do componente chamado Consumer, que será responsável por receber e exibir o fluxo multimídia. A exibição do fluxo multimídia é feita usando as bibliotecas do JMF (Java Media Framework) [46]. Consumer possui um atributo que representa o tipo do vídeo consumido (videoType). Esse atributo pode ser acessado via interface controladora de atributos application.cs.IAttrConsumer. Como 63 esperado, Consumer também possui uma interface de stream para entrada de dados (role=Input) com nome in. De maneira semelhante teremos a definição do componente servidor logo em seguida, como mostrado na Figura 23. O componente chamado server possui uma interface provida (role=Server) chamada iserver. É através dessa interface que o servidor disponibiliza a possibilidade do cliente enviar comentários sobre o filme em execução. Ela representa a interface Java application.cs.IService, que é a mesma usada pelo cliente. Figura 23 - Especificação do estudo de caso (parte dois). Assim como no cliente, o servidor possui uma interface requerida chamada icrypt_clt para um serviço de criptografia. Internamente no servidor, é definido o componente producer. O produtor é responsável por enviar bytes de um vídeo para o consumidor. Dessa forma, ele possui um atributo chamado videoName que indica o nome do vídeo usado no streaming. Como esperado novamente, o produtor define uma interface de stream para saída de dados (role=Output) chamada out. Ainda sobre a Figura 23, podemos ver os bindings estabelecendo os relacionamentos entre os componentes. O primeiro Binding (bind_crypt_clt) liga client e crypt, enquanto o segundo (bind_crypt_srv) liga server e crypt, satisfazendo as interfaces para criptografia 64 requeridas pelo cliente e pelo servidor. Logo em seguida, um terceiro Binding liga o cliente ao servidor, através da interface definida para o serviço que tem como assinatura application.cs.IService. Finalmente, chega o momento de conectar os componentes participantes do streaming multimídia através de suas interfaces de stream. Dessa forma, uma Connection, chamada conn, é criada tendo como origem (source) a interface out do producer e como alvo (target) a interface in do consumer. As demais propriedades da conexão também são configuradas, como protocolo, buffer, etc. Na Figura 24 podemos ver a parte final da especificação da aplicação, mostrando uma política de QoS criada para a conexão chamada conn estabelecida anteriormente. A frequência de monitoramento dessa política é a cada 5000ms. Ela define duas restrições sobre o RTT, uma se ele é maior que 5 (c1) e outra se ele é menor que 5 (c2). A primeira condição, chamada test1, diz que se a restrição c1 ocorrer, então execute a ação de mudar o protocolo da conexão para UDP. A segunda condição, chamada test2, diz que se a restrição c2 ocorrer então execute a ação de mudar o protocolo da conexão para RTP. Figura 24 - Especificação do estudo de caso (parte três). Uma vez definida a especificação da aplicação deve-se criar as classes e interfaces indicadas nas definições dos componentes. Por exemplo, na Figura 25 e na Figura 26 são mostradas, respectivamente, a interface application.cs.IService e a implementação do componente server. Figura 25 - Interface application.cs.IService. 65 Figura 26 - Implementação do componente server (appliation.cs.Server). Ainda sobre a figura acima, note que o server realiza a interface IBindingController, para permitir a troca de sua referência para o componente de criptografia. Nesse sentido, foram definidos dois componentes de criptografia para a aplicação. Suas definições são mostradas na Figura 27. Os dois componentes provêm a interface application.cs.ICrypt, porém são implementados usando algoritmos de criptografia diferentes. Figura 27 - Definição dos componentes para criptografia. O método principal da aplicação (método main) deve carregar a descrição da aplicação e solicitar o início da transmissão do fluxo multimídia, o que pode ser definido em poucas linhas, como mostrado na Figura 28. Figura 28 - Método principal da aplicação (main). 66 Para permitir que os recursos adaptativos sejam testados com mais flexibilidade, um conjunto de janelas (interface gráfica) foi implementado, possibilitando solicitar adaptações, digitar e visualizar os comentários enviados ao servidor. Esse conjunto de interfaces é mostrado na Figura 29. Podemos ver uma janela com a descrição da aplicação do lado esquerdo. Essa janela é atualizada a cada cinco segundos. Logo ela irá sempre refletir a estrutura atual da implementação, o que é possível através do componente Model2ADL. Do lado direito, no canto inferior, temos o player com o vídeo em execução, enquanto que no canto superior é mostrada uma janela com informações sobre parâmetros da conexão multimídia, com a possibilidade de solicitar alteração de várias propriedades da conexão. No meio da figura temos a interface gráfica que permite escrever comentários, bem como solicitar a troca entre os componentes responsáveis pela criptografia, e, logo abaixo, outra janela que mostra todos os comentários recebidos pelo servidor. Figura 29 - Conjunto de janelas da aplicação. Através desse estudo de caso podemos verificar as funcionalidades fornecidas pela implementação atual do protótipo relacionadas com vários aspectos, inclusive com o suporte para adaptação dinâmica, tanto em uma situação de troca de serviços representados por interfaces providas ou requeridas, quanto na adaptação do streaming multimídia. 67 5 MEDIÇÕES INICIAIS Este capítulo mostra algumas medições iniciais relacionadas ao tempo de adaptação para a troca simples de um componente. Os tempos foram medidos em dois computadores ligados por um Switch 10/100. As configurações são: PC-1: Sistema operacional Windows 7 32 Bits. Processador Intel Core 2 Duo ~2.2 GHz. Memória RAM 2.0 GB; PC-2: Sistema operacional Windows 7 64 Bits. Processador Intel Core i3 ~2.3 GHz. Memória RAM 4.0 GB; Basicamente, o tempo que será apresentado é o necessário para realizar todos os passos mostrados no diagrama de sequência da Figura 7. Uma pequena aplicação foi implementada para isso. Essa aplicação e as etapas para realizar a troca do componente são mostradas na Figura 30. Um cliente (Client) usa um serviço remoto que imprime informações do sistema no Console. O componente PrinterPT usa o idioma português para imprimir essas informações, enquanto o componente PrinterEN usa o idioma inglês para tal finalidade. Figura 30 - Aplicação usada para medir o tempo de troca de um componente. Como tentativa de comparar o resultado com algum outro trabalho, uma troca similar foi implementada usando o modelo de componentes Fractal [5]. O resultado de 30 execuções é mostrado no gráfico da Figura 31, enquanto o tempo médio pode ser visto na Figura 32. 68 Figura 31 - Tempo para adaptação em 30 execuções. Figura 32 - Tempo médio para adaptação. Podemos perceber que para a situação testada o FRAME teve tempos menores. Porém, enquanto o FRAME apresenta tempos menores em um cenário remoto, como este que foi testado, o Fractal apresenta tempos menores, próximos de zero, em um cenário local. Isso acontece devido o FRAME ter sido projetado para sempre trabalhar com o RMI em todo processo de configuração, seja ele local ou remoto. Enquanto que o Fractal usa referências diretas em situações de configuração local. Porém, como já dito, em uma situação remota, que é o mais comum, o FRAME apresentará tempos menores. Sem falar que o Fractal não trata de questões multimídia, ou do monitoramento de políticas de QoS. 69 6 TRABALHOS RELACIONADOS O tema de adaptação dinâmica tem sido bastante discutido ao longo dos últimos anos. Como consequência várias abordagens foram propostas ao longo desse tempo. A maior parte dessas abordagens propõem plataformas voltadas para sistemas distribuídos em geral. Neste contexto, o OpenCOM [4] é um modelo de componentes leve e eficiente elaborado para dar suporte à construção de sistemas adaptativos. Os conceitos fundamentais do OpenCOM são as interfaces, os receptáculos e as conexões. As interfaces expressam serviços providos pelos componentes, os receptáculos expressam serviços requeridos e as conexões são as ligações entre uma interface de um componente com o receptáculo de outro. O modelo fornece um conjunto de metainterfaces de forma a apoiar a adaptação dinâmica que consiste na adição e remoção dos componentes e seus relacionamentos. A proposta prima pela simplicidade e limita-se a fornecer suporte para adaptação dinâmica e reflexão computacional em sistemas in-process, ou seja, não há suporte nativo para distribuição. Outra limitação é que não há suporte direto para a composição de componentes, ou seja, componentes que contém subcomponentes. Por outro lado, o OpenORB (Open Object Request Broker) [4] é um middleware reflexivo e adaptativo construído usando o modelo de componentes OpenCOM, sendo este a base de sua implementação. O projeto do OpenORB busca resolver as limitações do OpenCOM. Sendo assim, há suporte para bindings locais e distribuídos, além do conceito de CF (Component Framework) que busca oferecer suporte à composição de componentes. CFs nada mais são do que uma coleção de regras e interfaces que governam as interações de um conjunto de componentes conectados dentro dele. Outro modelo semelhante ao OpenCOM é o Fractal [5]. O Fractal é um modelo de componentes reflexivo que oferece suporte para adaptação em tempo de execução e possibilita a criação de componentes de forma hierárquica, recursiva e compartilhada. A distribuição dos componentes não é fornecida diretamente pelo núcleo do modelo, mas pode ser conseguida com o uso de complementos, neste caso é possível usar o FractalRMI [47]. O framework OSGi constitui o núcleo das especificações da plataforma de serviços OSGi [48]. O framework gerencia a instalação e atualização de aplicativos no ambiente OSGi de forma dinâmica e escalável. As funcionalidades do framework são divididas em cinco camadas: segurança, módulo, ciclo de vida, serviços e serviços atuais. O framework permite selecionar implementações em tempo de execução através de um serviço de registro. Aplicativos podem registrar novos serviços, receber notificações sobre o status dos serviços 70 ou procurar por um serviço existente. Isso permite adicionar novas características à aplicação que pode ser modificada e atualizada sem precisar reiniciar o sistema. Em [49] discute-se o tema de adaptação no sentido de arquiteturas de software autoorganizáveis (self-organising), na qual os componentes automaticamente configuram seus relacionamentos de acordo com uma especificação arquitetural. O objetivo da proposta é minimizar o grau de gerenciamento explícito para construir e posteriormente evoluir o sistema, preservando as propriedades arquiteturais de sua especificação. O trabalho usa restrições arquiteturais como base para a especificação, projeto e implementação de arquiteturas auto-organizáveis para sistemas distribuídos. O trabalho descrito em [17] trata sobre adaptação em tempo de execução no sentido de propor uma abordagem baseada em modelos para sistemas autorrecuperáveis (self-healing). Um sistema autorrecuperável é aquele capaz de detectar e recuperar-se automaticamente de erros durante sua execução como, por exemplo, realizar a substituição de um componente que deixou de funcionar. A proposta é manter um ou mais modelos de representação do sistema em tempo de execução, de modo que alguma entidade externa possa realizar uma análise desses modelos de representação identificando problemas e tentando resolvê-los. Na abordagem proposta, o processo de recuperação passa pelas etapas de monitoração, interpretação dos resultados, resolução do problema e efetivação da adaptação. As soluções apontadas acima são abordagens para sistemas distribuídos de uma maneira geral. Para que elas sejam usadas em um sistema multimídia distribuído, o desenvolvedor ainda teria que tratar questões que não são suportadas nativamente, como aspectos ligados a qualidade de serviço e interfaces específicas para realização de streaming multimídia. Idealmente, uma proposta para sistemas multimídia distribuídos teria que abranger não apenas as características citadas nos trabalhos acima, mas também tratar das questões adicionais inerentes ao aspecto multimídia. Outro ponto é que apenas os dois últimos trabalhos citados ([17][49]) consideram a questão da autoadaptação. Serão descritas a seguir, em maiores detalhes, algumas propostas que se relacionam de maneira mais próxima com o FRAME, à medida que tratam questões ligadas ao aspecto multimídia distribuído e adaptação dinâmica. Os dois primeiros trabalhos citados a seguir apresentam metamodelos para sistemas multimídia distribuídos, enquanto os demais são abordagens de middleware ou frameworks para sistemas multimídia distribuídos. 6.1 Um Metamodelo Para QoS e sua Realização na Infraestrutura CORBA O trabalho proposto em [12] descreve um metamodelo para especificação de requisitos de QoS e sua realização na plataforma de componentes CORBA (Common Object Request 71 Broker Architecture) [50]. Para isso o trabalho estendeu o CCM (CORBA Component Model) [29]. A primeira extensão teve como objetivo permitir ao CCM suportar os novos conceitos definidos no metamodelo proposto para especificação de QoS. Já a segunda extensão permitiu incluir a possibilidade de modelar interações entre componentes através de portas de stream para o caso de troca de fluxos multimídia. Essa segunda extensão definiu um novo metamodelo que também foi integrado ao CCM, permitindo o uso dessa nova forma de interação. O metamodelo proposto para QoS possui dois pontos chave. O primeiro é o suporte para a especificação de contratos de QoS e o segundo ponto é o suporte para a modelagem de bindings que conectam as interfaces. Uma limitação da abordagem é que o metamodelo de QoS não integra estratégias de adaptação, ou seja, o que fazer quando o contrato de QoS estabelecido for quebrado, o que é coberto pelo metamodelo apresentado pelo FRAME através das ações de adaptação definidas nas políticas de QoS. 6.2 Um Framework Para Entrega Dirigido Por Qualidade Em [13] é proposto um framework para QDD (Quality-Driven Delivery) em ambientes multimídia distribuídos. QDD refere-se à capacidade do sistema entregar documentos, ou objetos, considerando as expectativas do usuário em termos de requisitos não funcionais. Dessa forma, é proposta uma abordagem dirigida por modelos focando a transformação e modelagem de informações de QoS. Os modelos e metamodelos de QoS são usados durante diferentes atividades como no mapeamento de requisitos para restrições do sistema, na troca de informações de QoS, na checagem da compatibilidade entre informações de QoS e na tomada de decisões. O modelo de QoS é construído com o conceito de dimensão de qualidade. Dimensões de qualidade são usadas para descrever características objetivas ou subjetivas relacionadas com os níveis de qualidade dos diferentes atores envolvidos no serviço de entrega ou com os níveis de qualidade do serviço de entrega esperados pelo usuário. O framework segue uma abordagem dirigida por modelos com foco apenas na modelagem de informações relacionadas à qualidade de serviço do sistema, tendo suporte para a representação de tomadas de decisão de QoS com base nas informações modeladas. As decisões de QoS são ações que podem ser realizadas em tempo de execução na tentativa de melhorar a qualidade de serviço provida. Dessa forma, decisões de QoS podem ser entendidas como as ações de adaptação 72 propostas no metamodelo do FRAME. A principal diferença entre esse framework e a proposta do presente trabalho, é que este apresenta uma abordagem de metamodelo mais completa. FRAME fornece suporte para a representação não apenas de informações relacionadas à qualidade de serviço e tomadas de decisão, mas também para os componentes do sistema e seus relacionamentos, o que não é coberto no framework para QDD proposto. Porém o presente trabalho não faz uso de dimensões de QoS, sendo preciso a indicação direta dos valores de QoS desejados, enquanto a proposta do framework para QDD permite a especificação de um escore, chamado de MOS (Mean Opinion Score), que representa uma nota do usuário indicando sua expectativa de qualidade de serviço. Os valores de MOS são mapeados para os valores reais de parâmetros de QoS, por exemplo, largura de banda. 6.3 PLASMA (PLAtform for Self-adaptive Multimedia Applications) PLASMA [6] é um framework que facilita a construção de aplicações multimídia autoadaptativas. É baseado no Fractal, um modelo de componentes projetado para desenvolvimento de sistemas de software reconfiguráveis. A abordagem proposta para reconfiguração é baseada na ideia de composição hierárquica fornecida pelo Fractal, de modo que uma adaptação pode ocorrer em diferentes níveis de composição. Assim, cada componente conhece sua própria configuração e possui um gerente de reconfiguração, de forma que cada componente é capaz de determinar uma maneira apropriada para alcançar uma dada reconfiguração, sendo o processo transparente para os níveis superiores. Ainda visando o suporte para reconfiguração o PLASMA definiu uma ADL dinâmica. Essa ADL possui construções apropriadas para descrever o comportamento dinâmico do sistema no que diz respeito às mudanças no ambiente. Informações convencionais como a estrutura e funcionalidades da aplicação também são suportadas pela ADL. O framework engloba três tipos principais de componentes: componentes de mídia, componentes de monitoramento e componentes de reconfiguração. Os componentes de mídia (media components) representam unidades computacionais usadas para a composição dos vários serviços multimídia. A arquitetura desses componentes pode ser decomposta em três níveis hierárquicos de outros componentes, cada um provendo funcionalidades específicas: Componentes MP (Media Primitive) são entidades de processamento de baixo nível. Eles implementam funções multimídia básicas como decodificação MPEG (Moving Picture Experts Group), codificação H.263, transmissão UDP, etc. Cada componente MP possui um conjunto de interfaces de stream usadas para receber e entregar dados; 73 Componentes MC (Media Composite) encapsulam funções de alto nível, chamadas tarefas (Tasks), como decodificação, codificação e transmissão em rede. Cada componente MC possui um conjunto de MPs que oferecem implementações para sua Task. Nesse sentido, os MPs são criados como subcomponentes dos MCs. MCs ocultam características de seus subcomponentes e possuem interfaces de binding para entrada e saída de dados, enquanto MPs possuem interfaces de stream. A diferença é que interfaces de binding podem estar ligadas a muitas outras interfaces de binding ao mesmo tempo; Componentes MS (Media-Session) são composições que encapsulam MCs. Um componente MS representa uma configuração de aplicação e expõe todas as características de controle que podem ser realizadas, por exemplo, operações de playback como start, pause, stop, forward, reward e outras. Adicionalmente aos três tipos de componentes de mídia citados acima, o framework define componentes de monitoração e reconfiguração que coordenam operações dentro da aplicação. Eles podem ser inseridos em qualquer nível de composição, como subcomponentes de um MC ou de um MS. A proposta apresenta três tipos de componentes nesse sentido: Sondas (probes): definem pontos de observação; Sensores (sensors): a função dos sensores é disparar eventos para ativar operações de reconfiguração; Atuadores (actuators): componentes primitivos (sem subcomponentes) responsáveis pela execução de ações de reconfiguração; Finalmente, após a ação de um atuador, o componente afetado irá seguir com uma operação para reconfiguração que pode ser: funcional, por exemplo, mudar o fator de qualidade da codificação, ou mudar o framerate do codificador; estrutural, adicionando e removendo componentes; ou ligada às políticas, por exemplo, alterar valores ou frequências de monitoramento das sondas, sensores ou atuadores. O esquema proposto de atuadores para reconfiguração possui a vantagem de tornar simples e transparente para a aplicação o processo adaptativo, uma vez que uma requisição de reconfiguração irá se resumir a alterar valores de atributos. Entretanto, a abordagem traz implicações ligadas à flexibilidade e a complexidade dos componentes. Primeiro, uma abordagem na qual a aplicação possa ter mais controle e alterar diretamente a estrutura do sistema pode ser menos transparente, mas é uma solução bem mais flexível. Segundo, a decisão de como realizar uma adaptação parte do componente que possui o atributo alterado, 74 o que implica que os componentes precisam ter uma complexidade maior associada a eles, além da própria implementação de suas funcionalidades. O presente trabalho permite uma abordagem mais flexível no sentido que é possível para a aplicação adicionar e remover componentes e relacionamentos diretamente. Obviamente, isso implica no aumento das responsabilidades da aplicação tornando o processo menos transparente. Entretanto, nada impede que os componentes do sistema sejam implementados seguindo uma abordagem semelhante ao do PLASMA. 6.4 Um Framework Para Adaptações Multimídia Baseado em Redes Dinamicamente Configuráveis e Reconfiguráveis O trabalho apresentado em [14] tem como objetivo fornecer um framework multimídia capaz de tratar uma vasta faixa de requisitos para adaptação e prover mecanismos de reconfiguração personalizáveis, de modo a se adequar às necessidades das aplicações. Tal personalização é obtida pelo uso de políticas descritas em uma linguagem de especificação de alto nível. Neste sentido, o framework fornece uma linguagem de especificação chamada APSL (Adaptation Proxy Specification Language). APSL permite a descrição de processos adaptativos como um grafo de tarefas multimídia relacionadas, além de oferecer construtores para expressar políticas de reconfiguração que definem como reagir às mudanças. Uma especificação escrita em APSL pode ser submetida a um interpretador (APSLInterpreter) integrante do framework. Esse interpretador mapeia a especificação em processos de adaptação. Em seguida um gerente de configuração (ConfigurationManager) constrói o processo de adaptação como uma composição de componentes multimídia, com cada componente implementando uma tarefa básica de modo a compor a configuração desejada. O framework considera dois tipos de eventos capazes de ativar uma reconfiguração: eventos de qualidade de serviço e eventos de estado dos recursos. O primeiro tipo está relacionado com a perda de pacotes, níveis de buffer, etc. O segundo tipo representa mudanças como carga de CPU, consumo de memória, tempo de vida da bateria, etc. Esses eventos são reportados para um gerente de reconfiguração (ReconfigurationManager) que decide quando e como as mudanças devem ser aplicadas. Uma reconfiguração realizada pelo gerente de reconfiguração é realizada em tempo de execução manipulando a configuração atual criada pelo gerente de configuração. Note que gerente de configuração e gerente de reconfiguração são entidades diferentes. As reconfigurações podem ser de dois tipos. O primeiro tipo se dá através da modificação de propriedades dos componentes, implicando mudanças em seu comportamento. 75 O segundo tipo executa uma reconfiguração estrutural, manipulando a configuração da aplicação em termos de componentes e seus relacionamentos, adicionando-os e removendoos. O framework distingue dois tipos de componentes: os componentes de rede e os componentes de processamento. Componentes de rede implementam protocolos de transporte (TCP, UDP) e de nível de aplicação (RTP, RTSP – Real Time Streaming Protocol, HTTP – Hypertext Transfer Protocol), podendo ser transmissores ou receptores. Os componentes de processamento são usados entre os transmissores e receptores transformando os dados, por exemplo, os codificadores e decodificadores ou algum tipo de filtro. Componentes de rede e processamento possuem interfaces de stream do tipo input e output para entrada e saída de fluxo de dados, respectivamente. No contexto desse framework, a configuração inicial e as reconfigurações são construídas por componentes diferentes, respectivamente o ConfigurationManager e o ReconfigurationManager. Na verdade, as funções dessas entidades são bastante próximas. Talvez uma abordagem mais simplificada pudesse usar um único elemento na tentativa de diminuir a complexidade arquitetural do framework. Nesta abordagem, os componentes comunicam-se apenas através de interfaces de stream. Isso implica que as informações trocadas entre os componentes limitam-se a fluxos de informação. Não sendo considerada para adaptação a possível relação entre os componentes por meio de interfaces para serviços requeridos ou providos, como deveria ocorrer em uma abordagem mais genérica, como a que foi apresentada pelo presente trabalho no FRAME. 6.5 PREMO (Presentation Environment for Multimedia Objects) O framework PREMO [15], proposto pela ISO (International Organization for Standardization), leva em consideração um extenso conjunto de requisitos para aplicações multimídia distribuídas. O PREMO define um modelo de objetos e de sincronização, assim como um conjunto de serviços multimídia. Os principais elementos arquiteturais do PREMO são: Recursos virtuais (Virtual Resources) são abstrações para descrição e controle de recursos. Eles podem encapsular dispositivos físicos, por exemplo, uma câmera, ou processos de software, por exemplo, filtros de áudio. A ideia principal é que um recurso é algo configurável e que precisa ser adquirido para se realizar uma tarefa. Recursos virtuais são as abstrações de mais alto nível no PREMO usadas como base para construção de outros elementos; Controles de streams (Stream Control) são responsáveis pelo controle, monitoramento 76 e sincronização de streams; Portas (Ports) são pontos de entrada ou saída para o fluxo de dados. O fluxo é direcionado de uma porta de saída (OutputPort) para uma porta de entrada (InputPort); Dispositivos virtuais (Virtual Devices) são os nós de um fluxo de dados em uma rede. Constituem o bloco básico para interação e processamento no PREMO. Dois dispositivos virtuais podem ser conectados por meio das portas; Conexões virtuais (Virtual Connections) são objetos que abstraem a comunicação entre os dispositivos virtuais. Uma conexão virtual abstrai o gerenciamento e transferência de dados de mídia permitindo controlar os dispositivos virtuais e portas participantes. Ela não realiza a transferência de dados; apenas é responsável por separar a conexão em diferentes elementos, permitindo o controle e negociações sobre as propriedades do fluxo e o suporte adequado em termos de quais tecnologias são usadas. Todos os atributos e operações dos objetos descritos pelo PREMO são definidos estaticamente. Entretanto, ele introduz o conceito de propriedade objetivando fornecer a flexibilidade provida por sistemas dinâmicos. Uma propriedade é um par formado por uma chave e uma sequência de valores. Na essência, uma propriedade é uma variável com tipo dinâmico que é manipulada em tempo de execução. O PREMO fornece operações capazes de definir, remover, ler e alterar uma propriedade dada sua chave. O comportamento dos objetos definidos para o sistema pode mudar de acordo com os valores dessas propriedades. O estabelecimento de uma conexão virtual no PREMO envolve três etapas básicas: definir o formato do fluxo que será negociado; estabelecer um mecanismo de comunicação entre a porta de saída e a porta de entrada; e definir os requisitos de QoS para a conexão. Feito isso a conexão virtual poderá ser local com buffer de dados compartilhado, ou remota com protocolos de comunicação. A maior limitação da proposta é que não existe suporte para adaptação estrutural, ou seja, troca, adição e remoção dos objetos definidos e seus relacionamentos, nem para adaptação de políticas de QoS. O framework PREMO possui um grande nível de complexidade, sendo incomum encontrar referências para sua implementação na literatura. Cabe, no entanto destacar que os conceitos do PREMO influenciaram outras propostas de frameworks como o A/V Streams [51] e o Cosmos [18]. 6.6 TOAST (Toolkit for Open Adaptive Streaming Technologies) TOAST [7] é uma plataforma de middleware baseada em CORBA voltada para 77 sistemas multimídia. No modelo proposto para o TOAST os componentes são as principais abstrações de processamento multimídia. Componentes podem trocar fluxos de dados através de interfaces de stream e de interfaces de fluxo. Interfaces de fluxo são fundamentais para interações multimídia no TOAST, podendo ser do tipo input ou output. As interfaces de stream são realizações diretas do modelo RMODP (Reference Model of Open Distributed Processing) [52] e agrupam uma ou mais interfaces de fluxo para um único ponto de interação composto. Um exemplo de uso para interface de stream é em uma chamada telefônica, que é bidirecional, pois contém dois fluxos de áudio unidirecionais; então poderíamos ter um par (input, output) de interfaces de fluxo para cada áudio e um par de interfaces de stream que encapsulam esses fluxos. Adicionalmente às interfaces de fluxo e stream, o TOAST também fornece interação entre componentes baseada em eventos. Assim, o programador pode dizer quais tipos de eventos cada componente deve receber em tempo de execução. As interações entre os componentes definidos pelo TOAST podem ser locais ou remotas, caracterizando um binding local ou distribuído. No caso de um binding distribuído a interação requer um objeto de binding (binding object) para representar a conexão, o qual é usado para permitir aos componentes interagirem através da rede ou entre espaços de endereçamento incompatíveis. Objetos de binding são criados por fábricas de bindings. O processo de criação é recursivo, assim fábricas de alto nível solicitam recursivamente às fábricas de mais baixo nível para criarem os objetos que forem precisos. Para oferecer suporte à adaptação dinâmica o TOAST adota os conceitos de implementação aberta e reflexão computacional. A primeira busca superar as limitações da abordagem “caixa-preta” abrindo aspectos chaves da implementação para o programador. Neste sentido, é comum usar a reflexão computacional que permite obter essa abertura separando o sistema em dois níveis, um com uma autorrepresentação do sistema e outro com a implementação do sistema. Para suportar adaptação é essencial que a aplicação tenha controle sobre os objetos de binding criados. Desse modo, o TOAST usa a ideia de open binding, que nada mais é do que a abertura do objeto binding por meio de uma metainterface. Essa interface permite à aplicação alterar a autorrepresentação da implementação (metanível), cabendo ao middleware refletir as mudanças na implementação base (nível base). No TOAST a autorrepresentação do sistema é modelada como um grafo de componentes, no qual os nós do grafo representam os componentes TOAST no nível base. A adaptação pode ocorrer de duas maneiras: minor adaptation e major adaptation. A 78 primeira é a mais básica das duas e permite realizar mudanças no modo de funcionamento interno dos componentes, por exemplo, em um codificador poderia ser alterada a qualidade de codificação de um vídeo. O segundo tipo de adaptação é mais agressivo e envolve alterações estruturais no grafo de autorrepresentação da implementação, permitindo adicionar e remover nós e arcos do grafo, em outras palavras, adicionar e remover componentes e seus relacionamentos na implementação. O TOAST modela apenas dois tipos de interações entre os componentes, sendo através das interfaces de mídia (interface de stream ou interface de fluxo), ou através de notificação por eventos. A primeira limitação que podemos apontar é que TOAST não modela relacionamentos funcionais entre os componentes, ou seja, dependências entre serviços providos e requeridos. Outra questão é que a autorrepresentação proposta modela apenas bindings entre componentes de mídia, os que se relacionam através das interfaces de mídia, não sendo tratados os relacionamentos originados por outros tipos de interações, como os eventos. A implicação prática disso é que apenas componentes de mídia podem ser trocados em tempo de execução, não sendo possível substituir, por exemplo, um componente monitor que gera eventos sobre a qualidade de serviço da transmissão. No FRAME, os relacionamentos funcionais são implementados pelas interfaces de serviço que podem ser clientes ou servidoras. Também não há limitação de quais componentes podem ser trocados. 6.7 Análise Comparativa Faremos uma comparação entre algumas características suportadas ou não pelas propostas dos trabalhos relacionados apresentados, incluindo a proposta do presente trabalho. Inicialmente é apresentado um quadro comparativo entre o metamodelo proposto pelo FRAME e as duas primeiras abordagens sobre metamodelos citadas nos trabalhos relacionados. As características consideradas foram: Representação das expectativas do usuário: esse ponto diz respeito ao uso de alguma técnica que permita ao usuário expressar seus desejos através de notas que são mapeados, em seguida, para os valores reais dos parâmetros de QoS; Representação de QoS: se o metamodelo suporta a modelagem e especificação de informações relacionadas à qualidade de serviço do sistema, permitindo definir regras, restrições ou contratos para os valores de determinados parâmetros; Representação dos componentes e relacionamentos: se o metamodelo permite que os componentes do sistema sejam representados, bem como seus relacionamentos 79 originados pelas dependências entre suas interfaces; Estratégias de adaptação: uma vez que o metamodelo permite a representação de informações de QoS, esse ponto diz respeito à possibilidade do metamodelo representar as ações ou decisões que devem ser tomadas quando os valores dos parâmetros de QoS não estão de acordo com o que foi especificado; Na Tabela 1 é apresentada a comparação considerando as características acima. Características não presentes são indicadas pela letra „N‟, enquanto características parcialmente fornecidas ou limitadas são indicas pela letra „L‟ e características completas são representadas pela letra „F‟. Tabela 1 - Comparativo entre metamodelos. Representação das Expectativas do Usuário Representação de QoS Representação de Componentes e Relacionamentos Estratégias de Adaptação Fonte Consultada QoS Para CORBA N F L F [12] Framework Para QDD F F L N [13] FRAME N F F F - Como pode ser observado, todos os metamodelos permitem a representação de informações de QoS. Com relação às expectativas do usuário apenas a segunda abordagem (framework para QDD) dá suporte através do uso de valores MOS, como indicado anteriormente. Esses valores representam escores fornecidos pelos usuários e são posteriormente mapeados para valores reais dos parâmetros de QoS. Sobre a representação de componentes e relacionamentos, foi considerado que apenas o FRAME oferece suporte completo, pois as outras duas abordagens tratam apenas da modelagem de QoS. Ainda assim, nessas outras duas abordagens, o suporte foi considerado parcial, pois as especificações de QoS modeladas são referentes aos parâmetros ligados à comunicação entre os componentes e tal comunicação, no fundo, representa um relacionamento entre esses componentes. No contexto do FRAME, este caso específico, é representado por uma conexão entre interfaces Input e Output. Finalmente, sobre as estratégias de adaptação, elas são consideradas pelo FRAME através das ações de adaptação e pelo metamodelo de QoS para CORBA através das decisões de QoS. A maior parte das abordagens que propõem metamodelos para sistemas multimídia distribuídos são focadas em pontos específicos, sendo o mais comum a modelagem de informações da QoS do sistema. Ainda há a necessidade de novas propostas de metamodelos 80 para sistemas multimídia distribuídos autoadaptativos, que tratem não apenas a modelagem de especificações de QoS, mas também de ações para adaptação e da representação dos componentes do sistema e seus relacionamentos, de forma a dar suporte ao mecanismo de adaptação baseada em modelos apresentada anteriormente, como é feito no FRAME. A seguir é apresentado outro comparativo considerando os demais trabalhos relacionados que apresentam abordagens de middlewares ou frameworks para sistemas multimídia distribuídos. As características analisadas foram: Baseado em componentes: se a proposta dá suporte para o desenvolvimento baseado em componentes; Reflexivo: se a proposta usa reflexão computacional; Suporte para serviços e streaming: respectivamente, se a proposta fornece suporte para uso e reconfiguração dos relacionamentos originados por interfaces funcionais que representam serviços providos e requeridos e por interfaces para streaming; Reconfiguração funcional, estrutural e de políticas: respectivamente, se a proposta permite reconfigurações via alteração de valor de propriedades ou atributos, se há suporte para modificação dos elementos do sistema e seus relacionamentos e se é possível alterar as políticas usadas para reconfiguração; Streaming local in-process, out-process e remoto: se a proposta fornece mecanismos de comunicação específicos para cada uma das possibilidades de comunicação, respectivamente, streaming no mesmo processo, entre processos locais e entre processos remotos; Autoadaptável, autorrecuperável e auto-organizável: respectivamente, se a proposta dá suporte para autoadaptação, se usa adaptação dinâmica para recuperação automática a falhas e se o sistema é capaz de resolver automaticamente, em tempo de execução, as dependências existentes entre seus elementos; Linguagem de programação: a linguagem de programação usada para implementar a proposta, ou pelo menos parte dela. O resultado da análise pode ser visto na Tabela 2. Novamente as letras „F‟, „L‟ e „N‟ representam, respectivamente, suporte completo, limitado e sem suporte. Tabela 2 - Comparativo entre as abordagens de middleware e framework apresentadas. Baseado em Componentes Reflexivo PLASMA F F TOAST F F APSL F L PREMO L N FRAME F F 81 Suporte para serviços Suporte para streaming L F N F N F N F F F Reconfiguração funcional Reconfiguração estrutural Reconfiguração de políticas L L L F F N F F F F N N F L F Streaming local in-process Streaming local out-process Streaming remoto F N F F F F N N F F F F F F F Autoadaptável Autorrecuperável Auto-organizável F N N N N N F N N N N N F N N C++ [6] C++/Java [7] C++ [14] Java [15] C/Java - Linguagem de programação Fonte consultada Primeiramente, a coluna da Tabela 2 chamada APSL indica o trabalho apresentado com nome “Um Framework Para Adaptações Multimídia Baseado em Redes Dinamicamente Configuráveis e Reconfiguráveis”. APSL é o nome da linguagem de especificação usada pelo trabalho e foi usada para manter um melhor layout da tabela. No PLASMA o suporte para serviços foi considerado limitado porque ele é oferecido apenas para componentes do tipo Media-Session. As reconfigurações foram consideradas limitadas também, apesar dos três tipos existirem, porque a decisão de qual adaptação realizar não pode ser feita diretamente pela aplicação, o que diminui a flexibilidade da abordagem, porém torna o processo de adaptação mais transparente. O mesmo ocorre com os componentes participantes de um streaming multimídia no FRAME. O FRAME permite a reconfiguração estrutural neste caso, porém através da alteração de propriedades da conexão. O gerente da conexão é quem irá determinar se é preciso realmente uma reconfiguração estrutural, não podendo a aplicação alterar essa decisão, por isso o suporte também foi considerado limitado para reconfiguração estrutural no FRAME. No caso do APSL o suporte reflexivo foi considerado limitado porque em nenhum momento os autores citam a reflexão computacional, mas a proposta parece ser reflexiva já que mapeia a configuração do sistema em uma autorrepresentação em tempo de execução. Com relação às linguagens de programação usadas, para o PREMO existe apenas uma descrição com alguns códigos de implementação na linguagem Java. Sobre o TOAST são indicadas duas linguagens, pois ele possui duas implementações, uma em Java e outra em C++. Já o FRAME possui apenas uma implementação, usando tanto a linguagem Java quanto 82 a linguagem C, já que esta é usada para implementar suporte à memória compartilhada. O FRAME, proposto pelo presente trabalho, fornece suporte para a maioria das características. Por um lado isso é positivo, pois o desenvolvedor de aplicações possui suporte para as principais características, mas por outro lado exige um esforço maior do mesmo no aprendizado de uso do framework e nas etapas iniciais de configuração para especificar quais características ele deseja usar. 83 7 CONCLUSÃO Este trabalho apresentou um framework reflexivo e baseado em componentes chamado FRAME que tem como objetivo dar suporte à construção de sistemas multimídia distribuídos autoadaptativos, fornecendo várias facilidades para o desenvolvimento e evolução de tais sistemas, como distribuição transparente e adaptação dinâmica. Apesar do domínio em questão ser multimídia, o framework é flexível o suficiente para ser usado em sistemas distribuídos de propósito geral. O framework proposto usa um esquema de adaptação baseado em modelos. Estes integram o metanível reflexivo das aplicações atuando como uma autorrepresentação do sistema. Dessa forma, para dar suporte à abordagem de adaptação baseada em modelos, foi apresentado o metamodelo definido pelo framework, o qual é usado para descrever os modelos em tempo de execução. Além do metamodelo, também foram apresentadas a ADL usada pelo framework, sua arquitetura, bem como o modelo de componentes com suporte para adaptação e reflexão. A arquitetura proposta é formada por dois componentes maiores. O componente FrameCore que engloba os principais componentes do framework, como parsers, configuradores e a implementação do metamodelo e o componente ModuleCommunication que é responsável pela comunicação multimídia, ou seja, streaming. O ModuleCommunication é resultado de trabalhos anteriores do grupo [20], como dito anteriormente. O núcleo fixo do framework (FrameCore) não é dependente do módulo de comunicação que é um ponto flexível podendo ser usado outro módulo desde que respeite as mesmas interfaces. Alguns estudos de caso foram apresentados buscando exemplificar a instanciação do framework. O primeiro focou a modelagem de uma aplicação multimídia através da ADL definida, mostrando como é possível especificar componentes, políticas de QoS e ações de adaptação. A aplicação modelada era formada por um componente principal composto de dois outros componentes, sendo um codificador, responsável por codificar e enviar o fluxo de vídeo, e um decodificador, que recebe o fluxo e decodifica-o. O estudo de caso permitiu apresentar como é possível especificar a aplicação e definir scripts de adaptação. O segundo estudo de caso permitiu verificar a possibilidade de desenvolver a aplicação usando apenas o framework e a linguagem Java, sem dependência da ADL. Por fim, o último estudo de caso buscou verificar a viabilidade do framework em um cenário com possibilidade de adaptação envolvendo tanto componentes multimídia (que manipulam fluxo 84 contínuo de dados através de uma InterfaceStream), quanto para componentes que possuem apenas interfaces de serviços, providas ou requeridas. Uma medição inicial dos tempos necessários para realizar uma troca de componente também foi realizada e comparada com os tempos obtidos com o modelo de componentes Fractal, constatando-se que os tempos do FRAME foram melhores para cenários remotos e piores para cenários locais. Algumas abordagens semelhantes foram comparadas com o presente trabalho e, de forma geral, o framework proposto apresentou-se mais completo do que essas abordagens. Primeiro, com relação aos metamodelos analisados, eles são propostos sempre para a modelagem de informações da QoS do sistema. Segundo, com relação aos middlewares e frameworks analisados, o FRAME é o que fornece suporte para a maior parte das características consideradas. Essas duas análises deixam clara que ainda há a necessidade de uma proposta mais completa para sistemas multimídia distribuídos autoadaptativos. Podemos resumir como principais contribuições do framework: A proposta do framework e sua arquitetura, dando suporte para adaptação baseada em modelos, abordagem ainda pouco explorada atualmente; A proposta de um metamodelo para aplicações multimídia distribuídas que serve como especificação geral para esse tipo de aplicação; A proposta de uma ADL dinâmica que pode ser usada para configurar e reconfigurar as aplicações multimídia distribuídas; Uma discursão e análise comparativa entre alguns trabalhos que tratam sobre adaptação e autoadaptação em sistemas distribuídos, mais especificamente em sistemas multimídia distribuídos. 7.1 Trabalhos Futuros Primeiramente, alguns pontos que ainda não foram tratados podem ser considerados para trabalhos futuros, incluindo: Permitir que componentes ou outros elementos sejam definidos como alvos de políticas de QoS. Nesse caso seria preciso verificar como as ações de adaptação seriam compatibilizadas com esses novos elementos; Permitir que a interface IConnectionController seja usada não apenas no momento da implantação do sistema, mas durante qualquer período da execução, o que permitiria uma abordagem com uma flexibilidade bem maior para troca de componentes integrantes de um streaming multimídia; 85 Concluir a implementação dos scripts de adaptação. Devido aos dois itens anteriores, as ações de adaptação via XML estão limitadas a ação do tipo Set, o que inviabiliza um script de adaptação dado que o mesmo não poderá ter outras ações como substituição de um componente, por exemplo; Atualmente é responsabilidade do próprio componente atualizar seus metadados caso ele mesmo altere seus atributos, sem usar a interface controladora de atributos definida para este fim. Para maior transparência essa responsabilidade deveria ser retirada do componente. Outras questões também podem ser abordadas visando aumentar o suporte do framework, como a implementação de novos módulos de comunicação ou novos protocolos multimídia para o módulo atual. Outra possibilidade é explorar a criação de novos estudos de caso buscando uma melhor avaliação do FRAME, bem como verificar o uso do framework com aplicações que usem outras bibliotecas para exibição do fluxo multimídia, por exemplo, nesse sentido, seria possível usar o GStreamer-Java [53] no lugar do JMF. Outro ponto interessante, no contexto de trabalhos futuros, é definir um novo modelo de distribuição para componentes e recursos do framework, de forma que traga para o nível de configuração alguns aspectos que sejam incorporados nas etapas de execução, permitindo, por exemplo, suporte para sistemas auto-organizáveis. O modelo de distribuição seria incorporado ao FRAME e compatível com a abordagem de loops de feedback. A questão de um modelo adequado de distribuição é particularmente importante para o FRAME, pois atualmente sua solução de distribuição é simples e limitada ao uso da tecnologia RMI (Remote Method Invocation). No FRAME, por exemplo, ainda não foram analisados quais requisitos devem ser observados por um protocolo para a comunicação entre os vários elementos configuradores do sistema, bem como ainda não foi definido o modelo ideal para gerenciar a distribuição dos dados do metanível entre os vários configuradores. Certamente, o modelo ideal é dependente de uma série de características que variam a cada situação, como contexto do ambiente e requisitos do usuário. Deve-se destacar que além de resolver as questões citadas um modelo de distribuição adequado permitiria, por exemplo, diferenciar adaptações locais e remotas. Neste caso, seria possível tratá-las de forma mais eficiente, o que não ocorre atualmente em um cenário local como foi evidenciado na comparação de tempos realizada entre o FRAME e o modelo Fractal. 86 REFERÊNCIAS [1] Rocha, C. G. A., Souza Filho, G. L. Um Framework para Provisão de Qualidade de Serviço em Redes IP. In II WORKSHOP RNP2, 2., 2000, Belo Horizonte. Anais… Rio de Janeiro: RNP, 2000. p. 207-218. [2] Taylor, R. N. T., Medvidovic N., Oreizy P. Architectural Styles for Runtime Software Adaptation. Proceedings of the 8th Joint Working IEEE/IFIP Conference on Software Architecture 2009 & the 3rd European Conference on Software Architecture 2009. Cambridge, England, September 2009. 171- 180. [3] McKinley, P. K., Sadjadi, S. M., Kasten, E. P., and Cheng, B. H. 2004. Composing Adaptive Software. Computer 37, 7 (Jul. 2004), 56-64. DOI=http://dx.doi.org/10.1109/MC.2004.48. [4] Clarke, M., Blair, G. S., Coulson, G., and Parlavantzas, N. 2001. An Efficient Component Model for the Construction of Adaptive Middleware. In Proceedings of the IFIP/ACM international Conference on Distributed Systems Platforms Heidelberg (November 12 - 16, 2001). R. Guerraoui, Ed. Lecture Notes In Computer Science, vol. 2218. Springer-Verlag, London, 160-178. [5] Bruneton, E., Coupaye, T., and Stefani, J.-B. Recursive and Dynamic Software Composition with Sharing. 7th International Workshop on Component-Oriented Programming (WCOP02), Monday, June 10, 2002 - At ECOOP 2002, Malaga, Spain, June 10-14, 2002. [6] Layaïda, O., Hagimont, D. PLASMA: A Component-based Framework for Building Self-Adaptive Applications. In Proc. SPIE/IS&T Symposium On Electronic Imaging, Conference on Embedded Multimedia Processing and Communications, San Jose, CA, USA, January 2005. [7] Fitzpatrick, T., Gallop, J. J., Blair, G. S., Cooper, C., Coulson, G., Duce, D. A., and Johnson, I. J. 2001. Design and Application of TOAST: An Adaptive Distributed Multimedia Middleware Platform. In Proceedings of the 8th international Workshop on interactive Distributed Multimedia Systems (September 04 - 07, 2001). D. Shepherd, J. Finney, L. Mathy, and N. J. Race, Eds. Lecture Notes In Computer Science, vol. 2158. Springer-Verlag, London, 111-123. [8] Councill, B. and Heineman, G. T. 2001. Definition of a Software Component and Its Elements. In Component-Based Software Engineering: Putting the Pieces Together, G. T. Heineman and W. T. Councill, Eds. Addison-Wesley Longman Publishing Co., Boston, MA, 5-19. [9] Klus, H., Niebuhr, D., and Rausch, A. 2007. A Component Model for Dynamic Adaptive Systems. In international Workshop on Engineering of Software Services For Pervasive Environments: in Conjunction with the 6th ESEC/FSE Joint Meeting (Dubrovnik, Croatia, September 04 - 04, 2007). ESSPE '07. ACM, New York, NY, 2128. DOI=http://doi.acm.org/10.1145/1294904.1294907. 87 [10] Zhou, J., Rautiainen, M., and Ylianttila, M. 2008. Metamodeling for Community Coordinated Multimedia and Experience on Metamodel-Driven Content Annotation Service Prototype. In Proceedings of the 2008 IEEE Congress on Services Part II (September 23 - 26, 2008). SERVICES-2. IEEE Computer Society, Washington, DC, 88-95. DOI=http://dx.doi.org/10.1109/SERVICES-2.2008.31. [11] Brun, Y., Marzo Serugendo, G., Gacek, C., Giese, H., Kienle, H., Litoiu, M., Müller, H., Pezzè, M., and Shaw, M. 2009. Engineering Self-Adaptive Systems through Feedback Loops. In Software Engineering For Self-Adaptive Systems, B. H. Cheng, R. Lemos, H. Giese, P. Inverardi, and J. Magee, Eds. Lecture Notes In Computer Science, vol. 5525. Springer-Verlag, Berlin, Heidelberg, 48-70. DOI=http://dx.doi.org/10.1007/978-3-642-02161-9_3. [12] Ritter, T., Born, M., Unterschütz, T., and Weis, T. 2003. A QoS Metamodel and its Realization in a CORBA Component Infrastructure. In Proceedings of the 36th Annual Hawaii international Conference on System Sciences (Hicss'03) - Track 9 Volume 9 (January 06 - 09, 2003). HICSS. IEEE Computer Society, Washington, DC, 318.1. [13] Kerherve, B., Nguyen, K. K., Gerbe, O., and Jaumard, B. 2006. A Framework for Quality-Driven Delivery in Distributed Multimedia Systems. In Proceedings of the Advanced int'L Conference on Telecommunications and int'L Conference on internet and Web Applications and Services (February 19 - 25, 2006). AICT-ICIW. IEEE Computer Society, Washington, DC, 195. [14] Layaida, O., Ben Atallah, S., Hagimont, D. A Framework for Dynamically Configurable and Reconfigurable Network-based Multimedia Adaptations. In Journal of Internet Technology, Special Issue on “Real time media delivery over the Internet”, October 2004. [15] Duke, D. J., Herman, I., Marshall, M. S. PREMO: A Framework for Multimedia Middleware: A Java description of the ISO/IEC Standard. Springer Verlag, February 1999. [16] Johnson, R. E. Components, frameworks, patterns. In Proceedings of the 1997 symposium on Software reusability (SSR '97), Medhi Harandi (Ed.). ACM, New York, NY, USA, 10-17. DOI=http://doi.acm.org/10.1145/258366.258378. [17] Garlan, D. and Schmerl, B. 2002. Model-based adaptation for self-healing systems. In Proceedings of the First Workshop on Self-Healing Systems (Charleston, South Carolina, November 18 - 19, 2002). D. Garlan, J. Kramer, and A. Wolf, Eds. WOSS '02. ACM, New York, NY, 27-32. DOI=http://doi.acm.org/10.1145/582128.582134. [18] Lopes, A. B. Um Framework para Configuração e Gerenciamento de Recursos e Componentes em Sistemas Multimídia Distribuídos Abertos. 2006. Tese (Doutorado). Faculdade de Engenharia Elétrica e de Computação, Universidade Estadual de Campinas, Campinas, 2006. 88 [19] Silva, C. E. Um Modelo de Interconexão de Componentes para Ambientes Multimídia Distribuídos. 2007. 115f. Dissertação (Mestrado). Programa de PósGraduação em Sistemas e Computação, Departamento de Informática e Matemática Aplicada, Centro de Ciências Exatas e da Terra, Universidade Federal do Rio Grande do Norte, Natal, 2007. [20] Júnior, I. F. V. Uma abordagem na camada de middleware para troca dinâmica de componentes em sistemas multimídia distribuídos baseados no framework Cosmos. 2009. 96f. Dissertação (Mestrado). Programa de Pós-Graduação em Sistemas e Computação, Departamento de Informática e Matemática Aplicada, Centro de Ciências Exatas e da Terra, Universidade Federal do Rio Grande do Norte, Natal, 2009. [21] Pinto, F. A. P., Lopes, A. B., Silva, A. G. P., and Silva, D. C. 2009. Um Modelo de Interconexão de Componentes Multimídia com Suporte à Seleção e Reconfiguração Dinâmica de Mecanismo de Comunicação. In Proceedings of the 15th Brazilian Symposium on Multimedia and the Web (Fortaleza, Brazil, 2009). vol. 1, 27-34. [22] Silva, A. G. P. Uma Abordagem Dirigida por Modelos para Desenvolvimento de Middlewares Auto-Adaptativos para Transmissão de Fluxo de Dados Baseado em Restrições de QoS. 2010. 106f. Dissertação (Mestrado). Programa de Pós-Graduação em Sistemas e Computação, Departamento de Informática e Matemática Aplicada, Centro de Ciências Exatas e da Terra, Universidade Federal do Rio Grande do Norte, Natal, 2010. [23] Pissias, P. Dynamic Reconfiguration in OpenCOM. Thesis (Msc – Master of Science). Computing Department, Lancaster University, Lancaster. 2005. [24] Kramer, J. and Magee, J. 1990. The Evolving Philosophers Problem: Dynamic Change Management. IEEE Trans. Softw. Eng. 16, 11 (Nov. 1990), 1293-1306. DOI=http://dx.doi.org/10.1109/32.60317. [25] Almeida, J. P., Van Sinderen, M., and Nieuwenhuis, L. 2001. Transparent Dynamic Reconfiguration for CORBA. In Proceedings of the Third international Symposium on Distributed Objects and Applications (September 17 - 20, 2001). DOA. IEEE Computer Society, Washington, DC, 197. [26] Klus, H., Niebuhr, D., and Rausch, A. 2007. A component model for dynamic adaptive systems. In international Workshop on Engineering of Software Services For Pervasive Environments: in Conjunction with the 6th ESEC/FSE Joint Meeting (Dubrovnik, Croatia, September 04 - 04, 2007). ESSPE'07. ACM, New York, NY, 2128. DOI=http://doi.acm.org/10.1145/1294904.1294907. [27] Paunov, S., Hill, J., Schmidt, D., Baker, S. D., and Slaby, J. M. 2006. Domain-Specific Modeling Languages for Configuring and Evaluating Enterprise DRE System Quality of Service. In Proceedings of the 13th Annual IEEE international Symposium and Workshop on Engineering of Computer Based Systems (March 27 - 30, 2006). ECBS. IEEE Computer Society, Washington, DC, 196-208. DOI=http://dx.doi.org/10.1109/ECBS.2006.39. 89 [28] Pollet, D., Ducasse, S., Poyet, L., Alloui, I., Cimpan, S., and Verjus, H. 2007. Towards a Process-Oriented Software Architecture Reconstruction Taxonomy. In Proceedings of the 11th European Conference on Software Maintenance and Reengineering (March 21 - 23, 2007). CSMR. IEEE Computer Society, Washington, DC, 137-148. DOI=http://dx.doi.org/10.1109/CSMR.2007.50. [29] OMG. CORBA Component Model, http://www.omg.org/technology/documents/formal/components.htm. V4.0, [30] Java Platform, Enterprise Edition (Java EE). Enterprise JavaBeans Technology, http://java.sun.com/products/ejb. [31] Box, D. 1997. Essential COM. 1st. Addison-Wesley Longman Publishing Co., Inc. [32] Lau, K. and Wang, Z. 2007. Software Component Models. IEEE Trans. Softw. Eng. 33, 10 (Oct. 2007), 709-724. DOI=http://dx.doi.org/10.1109/TSE.2007.70726. [33] IETF. The Internet Engineering Task Force (IETF), http://www.ietf.org. [34] IPPM. IP Performance Metrics (IPPM), http://datatracker.ietf.org/wg/ippm/charter. [35] IPPM. A One-way Delay Metric for IPPM, http://www.ietf.org/rfc/rfc2679.txt. [36] IETF. Network Time Protocol (Version 3): Specification, Implementation and Analysis, http://www.ietf.org/rfc/rfc1305.txt. [37] IPPM. A One-way Packet Loss Metric for IPPM, http://www.ietf.org/rfc/rfc2680.txt. [38] IPPM. IP Packet Delay Variation Metric for IP Performance Metrics (IPPM), http://www.ietf.org/rfc/rfc3393.txt. [39] IPPM. A Round-trip Delay Metric for IPPM, http://www.ietf.org/rfc/rfc2681.txt. [40] Oyamada, M. S., Gervini, A. I., Correa, E. F., Wagner, F. R., Carro, L. 2004. Análise de Desempenho e Consumo de Potência na Comunicação Interprocessos em Software Embarcado. In: X IBERCHIP WORKSHOP, 10., 2004, Cartagena de Indias. Resumos. UNIANDES, 2004. p. 108-109. [41] Farines, J. M.; Fraga, J. S.; Oliveira, R. S. Sistemas de Tempo Real. 1. ed. São Paulo: Escola de Computação 2000 da Sociedade Brasileira de Computação, 2000. v. 1, 201p. [42] Kropfberger, M. Multimedia Streaming Over Best Effort Networks Using MultiLevel Adaptation And Buffer Smoothing Algorithms. 2004. Thesis (PhD). Universitat Klagenfurt, Klagenfurt, 2004. [43] Eclipse. Ecore Tools, http://wiki.eclipse.org/Ecore_Tools. 90 [44] Eclipse. EMF – Eclipse Modeling Framework, http://www.eclipse.org/modeling/emf. [45] Dobson, S., Denazis, S., Fernández, A., Gaïti, D., Gelenbe, E., Massacci, F., Nixon, P., Saffre, F., Schmidt, N., and Zambonelli, F. 2006. A survey of autonomic communications. ACM Trans. Auton. Adapt. Syst. 1, 2 (Dec. 2006), 223-259. DOI=http://doi.acm.org/10.1145/1186778.1186782. [46] Oracle. JMF – Java Media Framework, http://www.oracle.com/technetwork/java/javase/tech/index-jsp-140239.html. [47] OW2 Consortium. Fractal RMI, http://fractal.ow2.org/fractalrmi. [48] The OSGi Alliance. OSGi Service Platform Core Specification. Release 4, version 4.2, june 2009. [49] Georgiadis, I., Magee, J., and Kramer, J. 2002. Self-organising software architectures for distributed systems. In Proceedings of the First Workshop on Self-Healing Systems (Charleston, South Carolina, November 18 - 19, 2002). D. Garlan, J. Kramer, and A. Wolf, Eds. WOSS '02. ACM, New York, NY, 33-38. DOI=http://doi.acm.org/10.1145/582128.582135. [50] OMG. Catalog of OMG Specifications: Middleware Specifications, http://www.omg.org/technology/documents/spec_catalog.htm#Middleware. [51] Sumedh Mungee, Nagarajan Surendran, Yamuna Krishnamurthy, and Douglas C. Schmidt. The Design and Performance of a CORBA Audio/Video Streaming Service, A chapter in the book Design and Management of Multimedia Information Systems: Opportunities and Challenges, edited by Mahbubur Syed and to be published by Idea Group Publishing, Hershey, USA, in 2000. [52] Blair, G. and Stefani, J., Open Distributed Processing and Multimedia, AddisonWesley, Harlow, England 1998. [53] GStreamer-Java. Java interface http://code.google.com/p/gstreamer-java. to the gstreamer framework,