Por motivos econômicos, vou referir-me a Service Provider apenas como SP.
Pré-requisitos para essa peleja
Para conseguir desenvolver satisfatoriamente um SP, é necessário um conhecimento intermediário-avançado sobre threads e desenvolvimento Win32. Além disso, será necessário ter um bom conhecimento sobre o desenvolvimento de DLLs em alguma plataforma de desenvolvimento, como por exemplo: Microsoft Visual C++, Borland C++ Builder ou outra qualquer.
Além disso é necessário ler o documento 1 da especificação CEN/XFS (na versão que se pretende para o SP), e o documento relativo a classe de dispositivo que se pretende desenvolver. Por exemplo, caso se esteja usando a especificação versão 2 de Dezembro de 1998, e o objetivo seja o desenvolvimento para uma impressora, os documentos necessários seriam: CWA13449-1.pdf e CWA13449-3.pdf.
Requisitos do SP
Tudo o que é preciso ter em um SP está descrito nos dois documentos da especificação indicados acima. No entanto, a seguir eu relacionou os requisitos chave de qualquer SP:
- Exportar as 11 funções WFPXXXXX descritas na especificação: são através dessas funções que se garante a aderência à especificação, por isso elas precisam existir no SP, e precisam também ter um comportamento aderente à especificação;
- Funcionamento assíncrono: O SP é assíncrono. Isso é muito importante, mas às vezes passa desapercebido. O ponto é que o protocolo de comunicação entre o SP e o XFS Manager é baseando em regras assíncronas. O XFS Manager é quem permite, artificialmente, que uma aplicação faça chamadas síncronas. Basicamente o que ele faz é aguardar o retorno do atendimento da request por parte do SP antes de retornar a chamada para a aplicação;
- Suportar multi-sessões: O SP precisa ser projetado para atender mais de uma aplicação ao mesmo tempo. Isso é muito importante, pois praticamente todos os sistemas de autoatendimento possuem agentes de monitoração que funcionam de modo não integrado à aplicação, e com isso um SP multi-sessão é indispensável;
Arquitetura do SP
Um SP tem, basicamente, duas grandes partes com responsabilidades bem definidas nas quais se concentram os componentes constituintes de qualquer SP:
- Estrutura compartilhada: Essa parte do SP é onde se concentra a maior complexidade desse desenvolvimento. Ela é comum a qualquer SP, sem mudanças (se for projetado corretamente). Em geral, se constrói um ambiente de desenvolvimento de SPs, onde essa parte é compartilhada entre todos os SPs da solução. Mas, essa parte tem tantos componentes críticos que são tão complexos que é muito comum que as empresas e pessoas comprem essa parte pronta de alguma outra empresa que já a tenha construída e debugada (que é o mais importante). Essa parte do desenvolvimento se concentra quase que inteiramente no documento 1 da especificação. Os componentes mais básicos dessa parte são:
- Gestor de Trace: responsável pela geração de logs do SP. Esse componente pode ser bem simples, onde apenas se escreve o que se quer em um arquivo de log, ou então pode ser bem complexo definindo níveis dos logs que serão gravados, estratégia de rotate, limite de tamanho e etc. Para essa parte, utilizar um framework de mercado como o log4cxx é uma alternativa bem interessante;
- Gestor de eventos: o SP é basicamente orientado à eventos, ou seja, ele envia e recebe eventos o tempo todo para poder informar que uma operação foi concluída ou que um marco foi alcançado no processamento ou ainda que um limite foi atingido;
- Agendador de requisições: o SP tem que ser assíncrono conforme os requisitos chaves. Isso quer dizer que qualquer comando que o SP receber deverá ser agendado para execução posterior. Isso é muito importante, pois é preciso prever que um mesmo comando será chamado várias vezes (várias aplicações acessando o SP). Com isso, o agendador precisa implementar uma estratégia de agendamento baseada em fila;
- Estrutura específica: Essa parte do SP muda de acordo com a classe de dispositivo e também de acordo com a interface do device driver. Essa é a parte do SP que precisa se comunicar efetivamente com o device driver, que é o controlador do dispositivo. Essa parte pode ser projetada de modo que o comportamento especifico da classe XFS seja resolvido junto com a interface do device driver. No entanto, a solução que mais me agrada é separar as duas coisas; Essa parte do desenvolvimento se concentra inteiramente no documento relativo a classe de dispositivo no qual o SP será construído. Os componentes mais básicos dessa parte são:
- Interface do Device Driver: este é o ponto de acesso ao dispositivo. Então aqui, em geral, existe uma classe com métodos que dão acesso a funções exportadas em uma dll ou lib do device driver que controla o dispositivo;
- Implementação da classe de dispositivo XFS: aqui deve ser implementado o comportamento específico da classe de dispositivo XFS de qual trata o SP. Por exemplo, se o SP for para impressora, então a classe de dispositivo é a PTR e deve-se então consultar a especificação dessa classe no conjunto de documentos XFS. No caso da impressora o documento é CWA13449-3.pdf;
Codificação
Aqui a dica é criar um projeto de DLL. Essa DLL precisa exportar as 11 funções previstas na especificação, e toda vez que essas funções forem executadas, uma sequencia de acontecimento deve ocorrer no interior do SP. Basicamente a sequencia é a seguinte:
- Verificar informações básicas a cerca dos parâmetros recebidos e também o estado em que se encontra a sessão. Por exemplo, um WFSExecute só pode ser executado após um WFSOpen. Ainda, se for executado um WFSLock, somente a aplicação que possui o "lock" poderá executar WFSExecute. As demais aplicações que não possuírem o "lock" poderão apenas consultar informações, executando, por exemplo WFSGetInfo;
- Agendar o processamento dessa "solicitação", armazenando todos os parâmetros da chamada em uma fila;
- Retornar WFS_SUCCESS para a chamada da função. Obviamente esse retorno significa apenas: "Ok, tudo certo até aqui, eu posso processar sua requisição...". Caso não seja esse o caso, precisa então ser retornado um código de erro que melhor indique o motivo pelo qual a solicitação não pôde ser atendida;
- Assim que possível, retirar solicitações da fila, analisar seus parâmetros e processa-los de acordo com a especificação para aquela classe de dispositivo. O resultado do processamento é SEMPRE um evento. Ou seja, mesmo que o resultado do processamento seja um erro, um evento deve ser gerado para o XFS Manager, informando-o desse resultado. Esse evento nada mais é do que uma mensagem windows, direcionada para o handle indicado nos parâmetros da chamada. Claro que isso aqui é uma aproximação simplista. De fato, existem mais questões envolvidas aqui como: verificar se não foi atingido o timeout para execução da solicitação, lançar eventos intermediários, notificar aplicações ouvintes que se registram para receber certo tipos de eventos e etc;
Testes
Bom, para testar o SP é necessário uma aplicação XFS para a classe de dispositivo em questão. Essa parte é bem mais fácil, e é possível construir rapidamente essa aplicação de testes. A aplicação pode ser inclusive construída para operar com uma interface de linha de comando. Para fazer essa construção basta utilizar o documento 1 da especificação, buscando informações sobre as funções WFSXXXX contidas no capitulo 4 (Application Programming Interface (API) Functions). A sequência básica de comandos para uma aplicação XFS é a seguinte:
- WFSStartUp;
- WFSOpen;
A partir daí, é possível executar os comandos específicos da classe utilizando os comandos WFSExecute e WFSGetInfo.
É isso. Té mais!!!


