Protheus no Linux – Parte 01

Introdução

O TOTVS Application Server ( ou Protheus Server ), bem como o DBAccess e outros produtos da TOTVS, também possuem versões para serem instaladas em Servidores e Desktops com sistema operacional Linux. Neste primeiro post, vamos ver como preparar uma VM com Ubuntu Server para instalar um TOTVS Application Server.

O Linux

Vou pular toda a parte histórica deste sistema operacional, você encontra muito material sobre isso na Wikipedia. Existem atualmente várias distribuições gratuitas e inclusive pagas de Linux, desenvolvidas para uso geral ou para cenários e ambientes específicos, versões “Server” — para servidores dedicados de aplicações — e versões “Desktop” — para uso diário de aplicativos com interface gráfica e janelas, entre outras para uso embarcado em dispositivos, etc.

Estreitando o leque de aplicações para os produtos TOTVS Application Server e TOTVS SmartClient, existem versões e distribuições de Linux homologadas para uso destas aplicações. Como cada distribuição possui versões diferentes e alguns comportamentos distintos, atualmente apenas versões de Linux “Server” são homologadas para o Protheus Server, e versões Desktop são homologadas para uso do SmartClient. A lista de distribuições e versões homologadas está na TDN, atualmente no link http://tdn.totvs.com/display/tec/Plataforma+homologada+dos+produtos

Ubuntu Server

O Ubuntu Linux é uma distribuição muito conhecida do Linux, derivada do Debian Linux, muito prática para instalação e atualização de softwares através do administrador de pacotes “apt-get”. Bem documentada, mantida por uma grande comunidade, possui versões Desktop e Server. Embora (até o momento) nenhuma distribuição Ubuntu esteja oficialmente homologada para uso do TOTVS Application Server, é muito simples criar um ambiente de testes ou desenvolvimento nesta plataforma.

Nada impede o uso desta plataforma em um ambiente de produção, porém como não foi realizado nenhum procedimento de homologação oficial da TOTVS neste sistema operacional, em caso de problema técnico de uma instalação nesta plataforma, não há suporte.

Criando a VM

Peguei uma ISO do Ubuntu Server no site oficial do Ubuntu, especificamente a versão “Ubuntu Server 14.04.4 64 Bits”. ( arquivo “ubuntu-14.04.4-server-amd64.iso”, disponível em http://releases.ubuntu.com/trusty/ ) . Criei uma VM usando um VMWare Player (versão gratuita para fins não-comerciais), com 32 GB de disco, 2 GB de RAM, 2 Cores, e uma interface de rede “Bridged — para a minha VM ter acesso a Internet.

VM Details

Instalando o Ubuntu Server 64

Inicialmente, você baixa a ISO de instalação no seu HD, e configura o Drive de CD da VM para iniciar com o disco montado. Ao iniciar a VM, aparece a tela de seleção de idioma de interface. O Ubuntu já tem a portabilidade para português do Brasil, eu particularmente gosto de usar o S.O. em Inglês mesmo.

Após escolher o idioma pressionando <enter>, será mostrada a tela inicial de setup. Para escolher a instalação mínima de sistema, pressione F4. Será mostrado um pop-up com algumas opções, selecione com as setas a opção “Install a minimal system”, pressione Enter para confirmar a escolha. Feito isso, pressione <Enter> novamente para iniciar a instalação do Ubuntu Server. Escolha agora o idioma de instalação (English, please…)

Na próxima tela, informe onde você está. Vamos informar que estamos no Brasil mesmo. Selecionamos “Other” na escolha de território. Na tela seguinte, escolhemos “South América” … E, finalmente, “Brazil”. Na configuração de “Locale”, pode deixar United States mesmo. Agora o instalador pergunta se você quer detectar o modelo do seu teclado mediante alguns testes de teclas, ou se você quer escolher o modelo por uma lista. Recomendo usar o assistente, é bem simples. Após escolher o teclado, será executada uma etapa preparatória rápida, e em seguida será perguntado o nome no host para esta máquina. Eu chamei a minha de “ubuntu14” mesmo.

Depois, é perguntado o nome completo do usuário da máquina. Na sequência, é perguntado o nome desse usuário para identificá-lo no sistema operacional. No meu caso, “siga0984”. E, na sequência, é solicitada uma senha e confirmação de senha para o usuário criado. Na próxima tela, o instalador pergunta se você quer criptografar a sua pasta “home”. Estamos fazendo uma VM de servidor … não precisa criptogtafar a “home”. Agora, o instalador tenta pegar a data e hora atuais na Internet, e determinar sua localização. Normalmente ele acerta, basta confirmar onde você está (Time Zone) . E, na última parte, vêm o setup do disco. Vamos pra opção mais simples, “Guided – Use entire disk”.

Na sequência, o instalador mostra as escolhas realizadas para a partição de disco. Como a nossa VM têm apenas um HD virtual, basta selecioná-lo. E, na sequência, na próxima tela, o Linux já sugere as configurações finais, basta selecionar <Ok> e prosseguir. Ao confirmar esta etapa, começa efetivamente a instalação do Ubuntu Server. Após a cópia de alguns arquivos, o Ubuntu pergunta se você está usando Proxy, para configurar o “Package Manager” – através dele podemos atualizar de forma muito fácil o sistema operacional. Se vão está sendo usado nenhum proxy, deixamos o campo em branco e apenas teclamos <enter> para continuar.

Após um ou dois minutos configurando os pacotes e instalando o sistema, o instalador pergunta se você quer manter a sua instância atualizada automaticamente. Normalmente eu escolho “não”. Eu atualizo minha VM quando eu precisar ou quiser uma atualização. E, finalmente, a tela que todos esperamos: O que nós queremos de Software na nossa instalação ? Bem, para usar o Protheus e ter um acesso legal na VM, não precisamos mais do que as duas primeiras opções. Selecione-as com as setas e pressione a barra de espaços para marcar ou desmarcar.

A última pergunta é se você quer instalar o gerenciador de boot ( GRUB loader ) na sua VM … bem, eu nunca deixei de instalar, mas não deve fazer diferença alguma para um ambiente de testes virtualizado. E, em poucos instantes, o instalador informa que está tudo pronto, e você pode reiniciar a máquina ! Basta pressionar <enter> para continuar. Após a VM reiniciada, o boot já foi feito pelo HD da VM, e o Ubuntu pergunta pelo seu usuário. Informe o usuário que você criou na instalação, pressione <enter>, depois a senha, enter novamente. Pronto ! Bem vindo ao seu Ubuntu Server 64 bits !

Ubuntu 14 Start

Preparação do Sistema Operacional

Agora, de posse da nossa VM, vamos aplicar as atualizações de sistema operacional desde a distribuição desta versão… Para isso, digite no prompt de comando:

sudo apt-get update

Logo na execução, será perguntado novamente a senha do usuário atual. Mesmo que você já esteja logado, o comando “sudo” serve para executar uma instrução com permissões de “root” ou Super User do Linux. Logo, no primeiro uso, ele vai te pedir novamente a senha do seu usuário … Este comando vai atualizar a lista de pacotes de updates disponíveis nos sites oficiais do Ubuntu. Feito isso, execute o comando abaixo, para instalar as últimas atualizações das aplicações instaladas no seu ambiente:

sudo apt-get upgrade

Caso exista alguma versão nova a atualizar, a aplicação pergunta se você quer atualizar ou não. Digite Y e pressione ENTER para confirmar a atualização. O processo de atualização via fazer download e instalação automática dos pacotes de aplicativos do sistema operacional instalados no seu ambiente, automaticamente.

Terminada esta atualização, vamos aproveitar e instalar alguns pacotes, que serão necessários para etapas posteriores. Inicialmente, vamos instalar o “unzip”, usando o comando abaixo:

sudo apt-get install unzip

Para permitir um acesso via rede para a VM, e inclusive para usar um SFTP ( Secure FTP ) para transferir nossos arquivos e binários do Protheus para dentro da VM, precisamos saber qual é o IP dela na rede. Para isso, usamos o comando abaixo:

ifconfig

Ao ser executado, ele mostra as interfaces de rede da máquina. Uma delas deve ser a eth0, que tem um endereço IPV4 e outro IPV6. Vamos usar o IPV4, destacado em vermelho na imagem abaixo:

Ubuntu 14 ifconfig

Recomendo que você instale na sua máquina Windows um “Putty” e um “WINSCP”, para acesso via Telnet/SSH (Terminal) e acesso ao sistema de arquivos (SFTP), respectivamente. O acesso via Putty, ao invés de acessar pela janela do Host da VM, permite operações como copiar e colar texto entre o terminal da VM e a máquina Windows, você pode abrir mais de um terminal do Putty ao mesmo tempo na mesma máquina, etc… E, finalmente, para a última etapa de preparação, vamos “esticar” um pouco os limites de handles por aplicação do sistema operacional. Isto será necessário posteriormente para subir o APPServer.

Use o comando abaixo para editar o arquivo /etc/security/limits.conf:

sudo vi /etc/security/limits.conf

O editor “vi” não é muito amigável para quem está acostumado com editores visuais, mas quando a tarefa é apenas inserir duas linhas no final da tabela, não é tão difícil. Basta usar as setas para chegar ao final do arquivo, apertar a tecla [ESC], seguido da tecla I (maiúsculo, para entrar no modo de inserção de texto), e acrescentar as linhas abaixo:

* soft nofile 32768
* hard nofile 32768

Com isso, aumentamos para 32768 os limites de handles para todas as aplicações desta instalação de sistema operacional. Para salvar o arquivo, pressione ESC para acessar o prompt interno do editor, então digite a string “wq!” ( sem as aspas ) e pressione <enter>. Isto fará com que o arquivo seja salvo, com o novo conteúdo agora editado, e o editor de textos seja finalizado.

Ubuntu 14 Linuxconf

Feito isso, vamos reiniciar a VM usando o comando abaixo:

sudo reboot now

Após reiniciar a VM, confirme se o IP da VM continua o mesmo ( usando o comando ifconfig ), e faça o setup de uma conexão de terminal para a sua VM usando o Putty, e uma conexão SFTP usando o WINSCP. Ambas as conexões são SSH.

Conclusão

Nesta primeira etapa, finalizamos a criação de uma VM 64 bits com Ubuntu Server, deixando ela praticamente pronta para receber um TOTVS Application Server, um DBAccess 64 bits, um c-Tree Server 64 bits, e afins. No próximo post da sequência do Protheus em Linux, vamos abordar os detalhes da instalação de um TOTVS Application Server nesta VM 😉

Saudações a todos, desejo a vocês TERABYTES de sucesso 😀 

 

Anúncios

Protheus – do AP5 ao P11

Introdução

Desde o surgimento do Advanced Protheus 5.07 em 1999, até o Protheus 11, o produto ganhou novos módulos, funcionalidades e recursos. Desde implementações e extensões da Linguagem AdvPL, até o FrameWork AdvPL com MVC. Porém, até o momento não ouvi falar de nenhuma análise técnica entre as versões. Então, após ressuscitar alguns CDs de instalação antigos, e fazer algumas medições, eu cheguei a alguns números aproximados muito, muito interessantes.

Do Protheus 5 ao Protheus 11

Informações por Versão Ap5 Ap6 Ap7 Mp8 P10 P11
Tabelas (SX2) 991 1394 1681 1677 3700 6368
Índices (SIX) 2190 3124 4107 4249 8770 14868
Campos (SX3) 16306 22042 27087 27545 59420 103951
Campos Virtuais 1281 1746 2261 2104 5284 8890
Maior numero de campos 168 169 176 163 200 267
Maior tamanho de Registro 1794 3761 3761 3761 4022 4909
Tabela com mais índices 14 15 18 26 20 28
Índice com mais Campos 12 12 13 14 14 14
Índice com maior chave 152 203 212 214 232 505
Tamanho do RPO (MB) 28 44 44 36 60 174
Funções no RPO 15104 21665 24601 26177 46026 79811
Classes no RPO 57 57 61 287 603 2451
Resources RPO 2445 3604 4107 4455 7975 15928
Entrada no ERP – SIGAFAT
Memória Consumida (MB) 10,63 10,47 12,48 12,06 15,74 49,22
Chamadas de funções básicas do AdvPl 34690 35682 44170 36615 63844 377300
Chamadas de funções do Repositório 8423 8598 9128 3944 6444 53066
Chamadas de Operadores 514403 576713 614246 363848 589606 4287337
Memoria para Carga de Fontes (MB) 1,8 2,3 2,41 2,91 4,8 14,9
Fontes Carregados 38 44 47 52 72 215

Analisando por cima os dados encontrados, podemos ver que do Protheus 10 para  Protheus 11 houve um salto bem maior em relação às versões anteriores. Houveram muitas implementações no ERP, módulos novos, MVC, ferramentas, integrações e controles adicionais.

 

Ao migrar do P10 para o P11, muitos clientes precisaram refazer o “sizing” de máquina. Na verdade, sempre ao migrar de versão um “sizing” de máquina deve ser avaliado, pois dependendo do tamanho do ambiente, um aumento de consumo de memoria ou CPU de 10 % pode representar um número grande em valores absolutos. No caso do P10 para o P11, o salto foi muito grande, mesmo quem usava o P10 com uma folga razoável de hardware precisou mexer no parque de máquinas para escalar o ambiente.

Os dados obtidos com esta pesquisa são meramente informativos, e foram obtidos em sua maioria com as versões de repositório original do CD, e dicionários sem customização. Foi um trabalho muito gostoso rever as telas de todas as versões de produto que eu trabalhei direta ou indiretamente nos últimos 17 anos, funcionando em um Windows 10 😀

Evolução da Interface

A interface da aplicação ERP foi evoluindo e ganhando novos layouts e funcionalidades ao longo das versões do ERP Microsiga. No TDN, têm um post muito interessante, com vários prints de interface, de todas as versões do ERP Microsiga, desde as primeiras versões Windows (antes do Protheus), até o P12 !! Vale a pena conferir, você pode acessar pelo link http://tdn.totvs.com/display/framework/Microsiga+Protheus

Conclusão

Com o crescimento da plataforma de negócios e de todo o parque de soluções rodando em AdvPl em cima da plataforma TotvsTec, o desafio constante de aprimorar a plataforma e implementar recursos para tornar viável a implementação e operacionalização de soluções cada vez maiores faz parte da rotina diária de todos os colaboradores da TOTVS 😀

Desejo a todos TERABYTES de sucesso !!!

Abraços e Saudações 😉 

 

 

Damas em AdvPL

Introdução

Em 2006, eu fiz um jogo de Damas em AdvPL, para jogar contra o Computador. Não cheguei a reforçar muito o algoritmo de decisão, mas ficou bom o suficiente pra dar um pouco de trabalho. O fonte ainda está cm alguns remendos, ainda não está pronto para um post de fins didáticos, MAS, atendendo a pedidos no FaceBook, estou disponibilizando um Patch da P11 (RPO TOP / Português) do Jogo, para degustação 😀

O Jogo

Após aplicar o patch, basta iniciar o SmartClient com a função “U_APGAMES”, e será mostrada a interface abaixo, para você entrar com o NickName do Jogador.

Checkers003

Após inserir o NickName e clicar em “Iniciar”, inicia-se o jogo de Damas. Você joga com as pedras amarelas, e o computador com as azuis. Você inicia a partida. Para jogar, primeiro você clica em cima de uma pedra sua, depois clica no lugar onde a sua pedra deve ser movimentada, vide sequência abaixo:

Checkers006a

Checkers006b

Checkers006c

Assim que você jogar, o computador jogará uma pedra dele. E já é a sua vez de novo.

Regras

  • As pedras normais somente movimentam-se para a frente.Em nenhuma hipótese uma pedra normal movimenta-se para trás.
  • Não existe “assopro”. Se você oferecer uma ou mais pedras ao computador, ele é obrigado a comer a sua pedra, e vice-versa.
  • Se mais de uma pedra for oferecida, o adversário escolhe como e qual pedra ele vai atacar.
  • Ao chegar do outro lado do tabuleiro com uma pedra normal, ela vira uma “Dama”.
  • A Dama pode mover-se para a frente e para trás, mas apenas UMA CASA por vez.
  • O mecanismo de navegação do Computador é “reativo”, então para você ganhar o jogo, você tem que encurralar o computador e fazer ele entregar as suas peças.
  • É mais fácil vencê-lo em jogo aberto, havendo troca de peças, e você abrindo caminho primeiro para fazer uma Dama. Mas cuidado com as “arapucas”, ele pode oferecer “inocentemente” uma pedra, e limpar duas ou três suas. 😉

Patch

O Patch do jogo está disponível para download no link “https://github.com/siga0984/Blog/blob/master/tttp110_APGames.zip” . Basta abrir a página, e clicar em “View RAW”, no final da página, para o Browse fazer o Dowload do ZIP contendo o Patch.

Conclusão

Existem diversas melhorias previstas no design do jogo, e inclusive a separação completa do core do jogo e da interface, além da utilização de orientação a objetos. Uma vez passado a limpo, o jogo será disponibilizado na íntegra, co os fontes 😀

Espero que vocês gostem do desafio, joguem um pouco contra o algoritmo, postem seus resultados no FaceBook 😉 E se você gostou, faça como eu: Compartilhe 😀

Desejo a todos TERABYTES de SUCESSO 😀 Abraços 😉 

 

RunTime do AdvPL

Introdução

No primeiro post do Blog, em apenas um parágrafo foi dada uma definição bem sintética do que é o AdvPL: Trata-se de uma uma linguagem de programação estruturada com suporte a orientação de objetos, que roda em uma máquina virtual com arquitetura client-server e multi-plataforma.

Hoje vamos entrar um pouco mais fundo em algumas características da execução de um código AdvPL, desde a pré-compilação até a execução do Código. Mas antes, vamos com algumas definições.

Código AdvPL

A sintaxe da linguagem AdvPL é uma extensão da sintaxe xBase, mais conhecida pelo seu uso na linguagem Clipper. Um código fonte em AdvPL passa por uma etapa de pré-compilação, onde vários comandos são transformados em chamadas de funções, e “açúcares sintáticos” podem ser implementados, através de #defines, #translates, #command(s), #ifdef(s) e afins. Os comandos da linguagem AdvPL que realmente são “comandos” são as instruções de decisão e iteração, como WHILE, FOR, IF, ELSEIF , ELSE, CASE, END … praticamente todo o resto dos comandos são implementações feitas por #command, #xcommand ou #translate, que permitem você usar por exemplo um “comando” de abertura de tabela, como o comando “USE <cTabela> ALIAS <cAlias> [ SHARED | EXCLUSIVE ] [ VIA <cRdd> ] [READONLY] [NEW]”, que na etapa de pré-compilação vai ser transformando internamente na chamada da função DbUseArea().

Pré-compilação

Tanto o IDE como o TDS (versão anterior e atual do Ambiente de Desenvolvimento de aplicações AdvPL, respectivamente) trabalham com um pré-compilador (appre.exe). A partir do fonte AdvPL e dos respectivos #include(s) utilizados no código, a pré-compilação gera um novo arquivo, chamado de PPO (Pre Processed Output), e este sim é o código enviado ao AppServer para ser compilado.

Compilação

A compilação deste código gera um “ByteCode” em formato proprietário, interpretável somente pela máquina virtual do AppServer. O ByteCode gerado é criptografado e armazenado em um arquivo de repositório de objetos, configurado no AppServer para o ambiente onde os fontes estão sendo compilados. Damos o nome de “ambiente” a um espaço virtual de execução, que engloba um repositório de objetos e um ponto de acesso a uma pasta no disco (local ou remota via rede) para acesso a arquivos sob este identificador de ambiente, entre outras configurações de acesso a dados relacionais e comportamentos desejados para a instância do ambiente.

Repositório de Objetos

Armazena as funções e classes compiladas a partir dos fontes AdvPL, é fornecido pela TOTVS contendo as compilações dos módulos do ERP Microsiga do produto padrão. Contém também as funções do Framework AdvPL, usadas pelos fontes dos demais módulos, e que também são usados em customizações do produto, onde o próprio cliente pode criar um código em AdvPL, usando-se das funções básicas e de Framework AdvPL para customizar o produto padrão através de pontos de entrada (compilação de funções de usuário — USER FUNCTION(s) — com nomes especificos, onde existem pontos de chamada realizados pelo produto padrão do ERP), ou mesmo criando novas funcionalidades.

O repositório possui mecanismos de verificação de integridade e proteção de código, para evitar a engenharia reversa dos fontes compilados. A reversão de código é possível, e às vezes necessária quando um cliente por exemplo “perde” os fontes das customizações da versão em uso do seu ERP, e precisa delas no momento de uma migração de versão. O procedimento de “descompilação” neste caso é solicitado para a TOTVS mediante abertura de chamado, onde cada caso é avaliado.

O repositório de objetos também guarda arquivos de imagem (BMP,PNG,JPG), que podem ser inseridos em um Projeto AdvPL através do IDE/TDS e recuperados posteriormente em tempo de execução e usados diretamente por algumas funções, classes e comandos da linguagem que montam a interface da aplicação.

O Protheus 12 utiliza uma nova engine da máquina virtual do AppServer, com um novo formato de ByteCode, com mais instruções de baixo nível. Isto tornou o ByteCode ligeiramente maior, porém com ganhos de desempenho em alguns processos e funcionalidades.

Execução do AdvPL

Partindo de uma execução de um programa AdvPL, iniciado a partir do SmartClient, o SmartClient faz um HandShake com o AppServer via conexão TCP (ou SSL caso configurado), e solicita a execução de uma função. Ela pode ser uma “Main Function” — Função de entrada de módulo ou ferramenta do ERP — ou uma “User Function” — aplicações ou customizações criadas em AdvPL pelo próprio cliente.

Como o AdvPL é essencialmente dinâmico, os fontes do repositório são carregados na memória sob demanda, conforme as funções vão sendo chamadas. Quando o Menu do ERP é apresentado, todos os programas já carregados e executados até então, essencialmente fontes do Framework do AdvPL são mantidos na memória. Ao chamar uma opção de menu, o fonte e suas dependências são carregados sob demanda e executados, e quando o usuário encerra a opção e volta ao Menu do ERP, todos os fontes carregados desde o início daquela opção são descarregados da memória.

Quando a excecução é a chamada de menu da interface MDI (SIGAMDI), cada opção de menu cria um contexto e uma conexão separada com o AppServer, permitindo a execução de múltiplos programas sob a mesma interface, onde cada execução possui seu contexto e processo independentes. Cada opção de menu finalizada encerra o seu próprio conexto e descarrega todos os prograas da memória. Ao usar o mecanismo de Balanceamento de Carga do AdvPL, cada nova opção de Menu do MDI pode ser direcionada para o AppServer com menos processos em execução.

Para jobs, não existe balanceamento de carga nativo. Cada Job é executado na instância do serviço onde o AppServer está sendo executado. Hoje podemos emular um balanceamento realizando um RPC para um determinado serviço e subindo o job via RPC ( Nativo do AdvPL).

Atualmente o contexto de uma execução em AdvPL está implicitamente amarrado com uma Thread do Sistema Operacional. A arquitetura multi-thread do AppServer não estabelece afinidade entre as CPUS físicas do equipamento, o Scheduler de tarefas do sistema operacional e encarregado de distribuir as Threads e realocá-las por CPU a seu critério. Devido ao cenário extremamente variável de peso de execução das Threads, tentar estabelecer uma afinidade tende a ser pior do que deixar o sistema operacional escolher a CPU em uso.

AdvPL com interface – SmartClient

A execução de processos de interface AdvPL com o SmartClient é síncrona, a aplicação SmartClient é a resposável por renderizar a interface (Janela ou diálogo) construída pela aplicação AdvPL, e uma vez que a interface seja “ativada”, o AppServer passa a esperar por uma interação do usuário no SmartClient, como pressionar um botão ou preencher um campo. Entre ambos existe um mecanismo de verificação de conexão, chamado “pulso”. Quando o AppServer está aguardando por uma interação do usuário com a interface, mesmo que o usuário não dispare nenhum evento, a cada 60 segundos o SmartClient dispara um evento interno de “pulso” para o AppServer , para indicar que o SmartClient ainda está aberto. Caso o AppServer nao receba nenhum evento ou nenhum pulso do SmartClient em 3 minutos, ele assume que o SmartClient não está mais conseguindo se comunicar com o AppServer , e derruba/finaliza o processo em execução no AppServer , liberando os recursos utilizados ( arquivos e registros bloqueados, licenças, conexão com DBAccess,etc ).

Depuração de Código AdvPL

Através do IDE e/ou TDS, podemos depurar (ou “debugar”) um código AdvPL, colocando pontos de parada, inspecionando variáveis de memória, e determinando as etapas de execução (step into, step over, step out, run…). Deve-se tomar uma atenção especial no uso dos “Watches” de execução, pois a chamada de funções dentro de um “Watch” podem mudar o comportamento da aplicação, como por exemplo reposicionar o ponteiro de registro atual de uma tabela de dados, mudando o comportamento da aplicação enquanto ela está sendo depurada. Normalmente usamos os Watches para variáveis de memória. Através da Janela de Comandos do IDE/TDS, também podemos executar expressões, e até mudar conteúdos de variáveis durante a depuração através de instruções de atribuição. Isto pode ser útil em muitas situações.

Uso de memória

Normalmente a memória alocada por um programa é limpa quando o programa é finalizado. Durante a execução de código, existem algumas limpezas realizadas nos destrutores de componentes de interface, e no retorno ao stack (pilha) anterior após a execução de funções do Repositório de Objetos. Normalmente objetos são limpos quando não são mais referenciados, porém caso seja feita uma referência circular entre objetos, a limpeza somente ocorre quando a aplicação termina, ou quando for realizada explicitamente por uma função chamada “FreeObj()”.

Existem diversos recursos de monitoramento de memória do AppServer, um dos mais utilizados é a configuração DebugThreadUsedMemory, que pode ser habilitada no appserver.ini, na seção [GENERAL]. Esta configuração faz com que o AppServer mostre no Monitor de Processos do AppServer a quantidade de memória aproximada em uso por cada processo em execução.

Conclusão

Boa parte dos recursos mencionados neste tópico estão documentados no site oficial de documentação da TOTVS, o TDN (Totvs Development Network), que pode ser acessado no link http://tdn.totvs.com. O Post de hoje é só pra “molhar” o bico, os próximos posts em momento oportuno vão entrar em mais detalhes de cada uma destas operações 😀

Agradeço a audiência de todos, e desejo a vocês TERABYTES de sucesso !!! 

Abraços 😉

Acesso a dados – DBAccess

Introdução

Nos posts anteriores dos tópicos de acesso a dados, abordamos o mecanismo ISAM e o mecanismo relacional, e vimos alguma coisa do DBAccess da TOTVS, o Gateway de acesso a dados relacionais usado pelo Protheus Server. Hoje vamos aprofundar um pouco o conhecimento sobre esse Gateway, na forma de um FAQ, com muitas perguntas bem cabeludas …rs… seguidas das respectivas respostas.

O que é o DBAccess ?

O DBAccess é um gateway de acesso a dados para bancos de dados relacionais, utilizado pelo Protheus Server, para fornecer uma camada de abstração de acesso a arquivos usando a abordagem ISAM em um SGDB relacional, e uma camada de acesso de consulta relacional através de Queries.

Por que o DBAccess foi construído ?

As versões de ERP da Microsiga, antes do Protheus, originalmente foram concebidos para acessar os formatos de dados nativos do Clipper, que eram DBFNTX e DBFCDX, onde a aplicação acessava diretamente os dados. Com a utilização do driver do ADS Client no Clipper, foi possível utilizar o ADS Server, um SGDB ISAM com arquitetura client-server para o armazenamento dos dados do ERP.

Com o surgimento e popularização dos Bancos de Dados relacionais para baixa plataforma, onde os SGDBs relacionais permitiam mais recursos, consultas mais fáceis e mais rápidas, e novas funcionalidades, além de estender a capacidade do acesso a dados ISAM/xBase, houve a necessidade da Microsiga criar um Gateway de acesso a dados relacionais, que permitisse a execução do código legado (escrito em uma abordagem ISAM) em um SGDB relacional, e permitir acesso a novas funcionalidades disponíveis apenas no ambiente relacional.

Onde entra o TOPConnect nisso ?

O TopConnect foi a primeira geração de Gateways de acesso a dados, sua primeira versão foi concebida antes do Protheus, através de uma parceria comercial com uma empresa estrangeira de desenvolvimento de software. Ela permitia aplicações em Clipper acessar bancos de dados DB2/400 (IBM AS400), Sybase, Microsoft SQL 6.5, Sybase, PostgreSQL, Informix, DB2 UDB, Oracle 6, e MySQL. O TOPConect era escrito em C, e para cada SGDB existia uma versão específica do Gateway.

A Microsiga optou por desenvolver uma tecnologia própria de acesso, sendo assim desenvolvido o TOPConnect 4. Usando C++ com uma abstração de acesso a dados, o mesmo executável possuía as implementações para usar qualquer um dos SGDBs homologados. Como o Gateway é atrelado a versão de produtos do ERP Microsiga, a partir do Protheus 10 ele passou a chamar-se DBACcess, incorporando as implementações para as novas versões dos SGDBs. Com a fundação da TOTVS, o DBAccess passou a ser responsabilidade do Depto de Tecnologia da TOTVS.

O DBAccess consome muito recurso ?

Como um Gateway de acesso a dados, seu consumo de recursos de Memória é diretamente proporcional ao número de conexões, versus o número total de tabelas e queries abertas, versus o tamanho de registro da tabela. Seu consumo de CPU e Rede é diretamente proporcional à quantidade de requisições realizadas pela aplicação AdvPL ao gateway. O consumo é relativamente pequeno por tabela aberta, mas considerando um ambiente de 3000 conexões, onde cada pode abrir e manter abertas mais de 100 tabelas e queries, o consumo de memória pode atingir ou ultrapassar 4GB de RAM.

Como o DBAccess acessa o SGDB ?

O Acesso ao banco Oracle é feito via OCI (Oracle Client Interface), e todos os demais bancos são acessados via ODBC, usando a interface ODBC fornecida pelo fabricante do SGDB. É necessário que a ODBC ou OCI do SGDB em questão esteja instalada no equipamento onde o DBAccess será utilizado.

Por que o DBAccess não têm balanceamento de carga ?

Bem, como o acesso aos dados é feito apenas pelo SGDB, ele sempre será o destino final de todas as conexões. Então, não faz muito sentido “balancear” as conexões do DBAccess. Porém, em ambientes com mais de 2 mil conexões, pode ser muito interessante você usar mais de uma instância de DBAccess em máquinas distintas. Esta topologia é chamada de “DBAccess Distribuído”. Nesta topologia, um ou mais serviços de Protheus apontam para um DBAccess, e todos os DBACcess devem usar uma ODBC apontando para um único SGDB, além de cada DBAccess apontar para uma instância única, nomeada de “master”, que exerce o papel de servidor de locks de registro e locks virtuais.

O que acontece se eu colocar 2 DBAccess apontando para o mesmo Database ?

Se eles não estiverem configurados na topologia de “DBAccess distribuído”, cada um deles vai olhar para o seu próprio controle de emulação de Lock ISAM de registros. Neste caso, pode haver invasão de lock (duas conexões de instâncias distintas vão conseguir fazer RecLock() no mesmo registro), o que pode levar a quebra de integridade dos dados do registro, pois somente a última atualização irá prevalecer), e pode causar DeadLock em transações no SGDB.

Por que o DBAccess não usa o Lock do Banco de Dados ?

O mecanismo de bloqueio de registros do SGDB é de uso intrínseco do Banco de Dados, e não oferece a flexibilidade exigida para o mecanismo de acesso ISAM emulado. Mesmo se fosse construído um mecanismo de emulação direta no SGBD, a quantidade de IOs e instruções para emular isso no SGDB inivabilizariam seu uso por questões de desempenho. O mecanismo de Locks ISAM e Locks Virtuais é feito na memória do DBAccess, de forma muito rápida e eficiente.

Por quê existem os campos R_E_C_N_O_ e D_E_L_E_T_ ?

Como o TOPConnect surgiu devido a necessidade de executar um código escrito originalmente para engine ISAM, precisamos destes campos para emular o comportamento original do ISAM: Uma coluna interna para registrar a numeração sequencial de inserção (ordem física e identificador único de registro), e o campo “D_E_L_E_T” para marcar os registros que foram “marcados para deleção permanente” através da função DbDelete().

E por quê existe a coluna R_E_C_D_E_L_ em algumas tabelas ?

Quando foi implementado o conceito de criação de índice único nas tabelas do ERP, no Protheus 8 se eu não me engano, caso a tabela possua um índice de chave única definido pelo ERP, eu não posso ter um registro “ativo” na base com a mesma chave única. Porém, como as tabelas do DBAccess trabalham com o conceito de deleção “lógica” de registros, marcando os registros a serem eliminados fisicamente usando a função DbDelete(), eu posso ter um ou mais registros marcados para deleção, com a mesma chave única. Por exemplo, eu crio a tabela TESTE com a coluna CHAVE, e crio um índice de chave única com a coluna CHAVE. Se eu usar apenas esta coluna na minha chave única, se eu inserir um registro “000001”, depois deletá-lo ( campo D_E_L_E_T_ está com um “*”), e depois tentar inserir outro registro com “000001”, o SGDB não vai deixar …

Então, quando o ERP solicita ao DBAccess a criação de um índice de chave única, o DBAccess acrescenta na tabela a coluna de controle “R_E_C_D_E_L_”, coloca ela como último campo da chave única, e as colunas R_E_C_D_E_L_ de todos os registros marcados para deleção ( D_E_L_E_T_ = ‘*’) são alimentadas com o conteúdo do R_E_C_N_O_, e todos os registros não marcados para deleção ( ativos ) ficam com este campo ZERADO. Deste modo, eu posso ter um e apenas um registro não marcado para deleção com uma determinada chave única, mas eu posso ter um ou mais registros com o campo chave com este mesmo valor, caso eles estejam marcados para deleção.

Cada vez que o Protheus pede ao DBAccess para marcar um registro como “Deletado” através da função DbDelete(), o DBAcccess verifica se a tabela possui a coluna R_E_C_D_E_L_ , e atualiza ao mesmo tempo a coluna “D_E_L_E_T_” com ‘*’ e o R_E_C_D_E_L_ com o R_E_C_N_O_. Caso um registro seja recuperado, isto é, seja removida a marca de deleção, usando a função DbRecall(), a coluna R_E_C_D_E_L_ é atualizada para “0” zero. Deste modo, se você tentar inserir um registro ativo com uma chave duplicada, o SGDB não deixa fazer a inserção, e se você tentar desmarcar um registro deletado que tenha uma chave, e já existir um registro ativo (não marcado para deleção) com a mesma chave, o SGDB não permite a recuperação do registro, pois isto viola a chave única definida.

O que é mais rápido : Uma consulta ISAM ou por QUERY ?

Normalmente o acesso por Queries é mais rápido, sendo visivelmente mais rápido em leituras de registros sequencialmente. Um acesso de leitura no resultset de uma Query reflete os dados obtidos no momento que a Query foi executada. Já a leitura por acesso ISAM emulado retorna cada registro sob demanda, no momento que o registro é posicionado. A consulta por Query permite JOINS, para busca de dados de tabelas relacionadas. NO ISAM, você é obrigado a posicionar manualmente cada tabela relacionada e realizar a busca sob demanda.

Verdade que o DBSeek() é lento no DBAccess ?

Um DBSeek() no DBAccess procura posicionar no primeiro registro da ordem informada cujos campos que compõe a ordem do índice em uso que foram informados na instrução atendam a condição de busca. Se você faz um DBSeek() para posicionar no primeiro registro imediatamente superior a ordem desejada ( ou “SoftSeek” ) , DBSeek( cChave , .T. ) … o DBAccess pode submeter internamente várias Queries ao SGDB até achar o registro que satisfaça esta condição. Trocar um DBSeek() simples, que apenas verifica se um registro existe ou não, e trocar isso por uma Query, fatalmente vai ser mais lento, pois a abertua de uma Query para pegar apenas um registro vai usar 3 IOs, enquanto o DBSeek() faz apenas um. No caso da busca pelo último registro de uma determinada chave, uma Query pode ser mais rápida. Por exemplo, para saber qual foi a última data de um determinado evento, onde a tabela é indexada pelo código do evento mais a data, ao invés de pegar o código do evento, acrescentar uma unidade, procurar pelo primeiro registro da próxima sequência com uma chave parcial e SoftSeek, e depois fazer um Skip(-1) — coisa que é muito rápida e comum de ser feita no DBF — podemos simplesmente fazer uma query com “select max(datadoevento) as ultdata from tabela where codigodoevento = ‘xxxxxx’ and D_E_L_E_T != ‘*'”

E as inserções e Updates, são rápidas ?

Ao comparamos inserções via instrução direta “INSERT” e a inserção via DBAppend() — modo ISAM — , ambas são muito rápidas. A inserção tradicional de registros pelo AdvPL, usando DBAppend() e replace(s), possui um mecanismo de otimização que prioriza o envio das informações de inserção em apenas um evento de I/O. Porém, dependendo do que é executado durante a atribuição dos campos, enquanto o registro atual está em estado de inserção, o Protheus Server faz um “Flush” da inserção parcial, com os dados disponíveis até aquele momento, podendo executar mais I/Os de update para o mesmo registro enquanto a inserção não for finalizada. Este assunto será mais detalhado em um tópico específico de dicas de desempenho (Acelerando o AdvPL)

O que é o erro -35 ?

O código -35 é um código de erro genérico retornado pelo DBAccess quando a conexão com o SDGB não foi bem sucedida, OU quando a conexão não atendeu aos requisitos de operação com o SGDB. Para saber o que realmente causou o -35, o monitor do DBAccess deve ser acessado, e o registro de eventos de erro do DBAccess deve ser verificado. Pode ser desde o SGDB estar fora do ar, ou usuário e senha não configurados corretamente no DBAccess, falha de criação ou verificação de alguma tabela interna de controle do DBAccess, etc.

O que é o erro -2 ?

O erro -2 indica uma interrupção inesperada da conexão entre o Protheus Server e o DBAccess. Da mesma forma que o erro -35, o -2 pode ter diversas causas, desde um problema de rede entre o Protheus Server e o DBAccesse, ou entre o DBAccess e o SGDB, até um término anormal do processo que estava atendendo esta conexão no DBAccess (Assert Exception, Out Of Memory, Access Violation). Deve ser verificado o LOG do DBAccess para ver os detalhes do que aconteceu.

E os demais erros ?

Cada um possui um significado geral, para um tipo de operação que não foi bem sucedida. O código do erro apenas informa que uma operação falhou, porém somente descobriremos a causa efetiva da falha olhando o log de registro de erros do DBAccess. A lista de códigos de erro do DBAccess está na TDN, no link (http://tdn.totvs.com/pages/viewpage.action?pageId=6064500).

O DBAccess faz “leitura suja” de registros ?

Sim, para a grande maioria dos bancos. Devido a natureza das transações do SGDB, e da necessidade do comportamento esperado do AdvPL em ter acesso de leitura a qualquer registro sem espera ou bloqueio, mesmo que o dado esteja sendo alterado dentro de uma transação por outro processo, foi necessário definir explicitamente o nível de isolamento “READ UNCOMMITED”. O Banco Oracle não tem a possibilidade de leitura “suja”, ele é endereçado com “Read Commited”, mas ele permite que as demais conexões acessem a última versão committed, mesmo que exista uma transação aberta atualizando aquele dado.

O DBAccess “prende” conexões ?

Uma conexão feita pelo Protheus ao DBAccess faz o DBAccess abrir uma conexão no SGDB. Uma vez aberta, boa parte do tempo a conexão no DBAccess fica aberta, esperando o Protheus pedir alguma coisa ao DBAccess, como por exemplo: abrir uma tabela, uma query, posicionar em um registro, inserir um registro, executar uma Stored Procedure, etc. Ao receber uma requisição de abertura de Query, por exemplo, o DBAccess solicita ao SGDB a abertura da Query, e aguarda do SGDB um retorno ( sucesso ou erro). Enquanto isso, o Protheus fica esperando o DBAccess retornar. A Aplicação AdvPL estabelece a conexão com o DBAccess, e pode encerrar a conexão durante a execução da aplicação, e mesmo que o programa não desconecte, quando a Thread da aplicação AdvPL terminar, qualquer conexão com o DBAccess que tenha sido deixada aberta é encerrada. Existem algumas condições que o SGDB pode demorar a responder, como por exemplo um DeadLock no SGDB, a abertura de uma query muito complexa sobre um número muito grande de tabelas, a execução de uma Stored Procedure que fará muito processamento, etc.

Existe uma condição onde uma conexão pode ficar aberta no DBAccess, dando a impressão de estar “presa”: Caso a thread que está executando uma aplicação AdvPL, que consequentemente conectou no DBAccess, seja interrompida por uma ocorrência crítica de erro, como um Access Violation ou Segment Fault (Invasão de memória), e ocorra falha no destrutor da thread. O Processo em si não está mais no ar, mas a conexão permanecera aberta até que o serviço do Protheus seja finalizado.

E, existe também uma última condição, que pode fazer uma conexão no DBAccess permanecer aberta indefinidamente — ou até que o DBAccess seja finalizado, ou a conexão seja encerrada pelo DBAccess Monitor: Caso exista algum problema de rede entre a aplicação Protheus e o DBAccess, e ocorra uma queda na conexão TCP, quando o DBAccess está “IDLE”, esperando pelo Protheus pedir alguma coisa. Se a informação da perda da conexão não chegar ao Socket do DBAccess, ele vai ficar esperando indefinidamente, mantendo a conexão aberta e os recursos pertinentes alocados.

Existem estudos em andamento para criar novas funcionalidades na ferramenta, como permitir derrubar uma conexão do SGDB através do DBAccess, cancelando uma Query ou Stored Procedure, entre outros que eu não posso comentar agora …rs… Aguardem as próximas versões … 😀

Como o DBAccess encerra uma conexão pelo DBAccess Monitor ?

Um processo de conexão entre o DBAccess e um SGDB é mantido no ar enquanto existe a conexão entre o Protheus e o DBAccess. Logo, o DBAccess fica em um laço de espera por requisições. A cada intervalo de alguns segundos que o Protheus não envia nenhuma requisição, e a cada requisição recebida, ele verifica um flag de controle de processo, que indica se o DBAccess Monitor pediu para aquela conexão ser encerrada. Quando você pede ao DBAccess Monitor para encerrar uma conexão, ele apenas seta este flag no processo, que somente será considerado e avaliado quando o DBAccess está esperando por uma requisição do Protheus. Se  DBAccess pediu pro banco a execução de uma Stored PRocedure, que pode demorar de segundos a minutos, e neste meio tempo você pedir para a conexão ser encerrada através do DBAccess Monitor, ele somente vai encerrar a conexão com o SGDB quando a procedure terminar, e ele voltar ao loop de requisições. Se por um acaso você quer que a procedure ou query que está demorando seja interrompida, somente um DBA com acesso ao SGDB consegue derrubar o processo usando algum mecanismo de administração do SGDB.

E se eu derrubar o processo no SGDB ?

Se o DBAccess está executando algo no SGDB, e aguardando por um retorno, e o processo for finalizado no SGDB, o DBAccess receberá um retorno de erro, e repassa ao Protheus. Se o DBAcccess não estava fazendo nada no SGDB, e você derruba a conexão no SGDB …. O DBaccess somente vai “perceber” que a conexão foi pro espaço quando o PRotheus pedir alguma coisa, e o DBAccess for tentar pedir algo para o SGDB através da conexão que não existe mais …

Por que o DBAccess não traz campos MEMO em Query ?

Um campo MEMO pode conter muito mais dados em um campo do que em muitos registros. Uma tabela DBF por padrão traz todos os campos do registro atualmente posicionado a cada cada DbSkip() ou DBSeek(). Para ganhar desempenho e não onerar os processos do sistema que fazem leituras sequenciais em processamentos, os campos MEMO são trafegados somente sob demanda, quando abrimos a tabela em modo ISAM emulado, e somente quando a aplicação tenta ler ou acessar um campo Memo do registro atualmente posicionado.

Como os campos MEMO foram implementados no DBAccess para garantir a compatibilidade com o campo Memo do DBF, a forma de armazenar esta informação em cada SGDB é escolhida diretamente pelo DBAccess, a critério dele. Por questões de economia e otimização de recursos (estamos falando da aplicação que nasceu em um tempo onde uma rede 100 MBits era um “luxo”), foi decidido não retornar campos MEMO em Queries, o DBAccess não faz o Bind dos dados de campos usados como “Memo”. Por isso, se hoje você precisa da informação de um ou mais campos memo de uma tabela, você pode selecionar os dados necessários por Query, porém você recupera também o número do registro (R_E_C_N_O_) na Query, usando um outro nome para este campo, e mantendo a tabela original aberta em modo ISAM emulado, você posiciona no registro desejado usando DbGoto(), e então faz um Fieldget() do campo MEMO.

Quem alimenta o R_E_C_N_O_ da tabela na inserção de registros ?

O DBAccess possui um cache das estruturas de colunas e índices das tabelas, alimentado sob demanda, e um controle de numeração e locks. Ele guarda o número do ultimo registro inserido em uma lista em memória, e cada nova inserção incrementa o último registro da tabela na lista. Este processo é muito rápido, porém torna algo nada prático você fazer inserções através de uma Query ou Stored Procedure. Foi criado um mecanismo para permitir o DBAccess criar uma tabela com numeração automática de R_E_C_N_O_ pelo SGDB, disponibilizado para o FrameWork AdvPl, onde alguns novos módulos desenvolvidos no ERP Microsiga já se utilizam desta funcionalidade. Porém, isto ainda não é extensível para as demais tabelas dos módulos do ERP por questões de impacto. Todas as rotinas hoje escritas que alimentam tabelas, por exemplo via Stored Procedure, precisariam ser refatoradas para contemplar esta funcionalidade, pois nenhuma delas poderia mais fornecer um número de R_E_C_N_O_ ao fazer inserção na tabela, e imediatamente após a inserção, algumas delas precisam obter do SGDB qual foi o número do registro inserido.

Não é algo simples de ser feito, ainda mais “de uma vez”. Para cada SGDB o DBAccess define uma forma de criar o campo com auto-incremento, algumas usando um tipo de campo de auto-incremento do próprio SGDB, outas através de gatilhos criados internamente pelo DBAccess no momento de criação da tabela com estas características.

Para que serve a tabela TOP_FIELD, criada pelo DBAccess ?

Como a aplicação foi feita para emular ISAM, no momento da criação da tabela pelo Protheus, a estrutura da tabela é informada ISAM/DBF, onde especificamos campos do tipo “C” Caractere, “N” numérico (com precisão inteira ou decimal), “D” Data, “L” Lógico e “M” Memo. Porém, como o DBAccess escolhe cada tipo de campo que se adéqua melhor a necessidade, ele precisa guardar algumas definições que o Protheus forneceu na criação da tabela. E ele faz isso na tabenla TOP_FIELD.  Se você copia uma tabela diretamente de um Ddatabase para outro, no mesmo banco, mas não copia as definições da TOP_FIELD, todos os campos “D” data serão mostrados como “C” Caractere de 8 bytes, cmapos “L” lógicos serão “C” caractere de 1 byte, contendo “T” ou “F”, e todos os campos numéricos vão vir com uma precisão de 15 dígitos com 8 decimais.

Por quê as tabelas do DBAccess usam constraints DEFAULT ?

Não existe o valor “NULL” nas bases ISAM usadas pelo ERP Microsiga. Logo, mesmo que o campo esteja vazio, ele precisa ter o seu conteúdo default ( caracteres em branco, números com 0, data com string em branco, booleano com “F”). A aplicação conta com este comportamento, e as queries e joins foram construídas baseadas nesta premissa.

Como o DBAccess faz alteração estrutural na tabela ?

Através da função TC_Alter(), o DBAccess recebe a estrutura atual da tabela e a nova estrutura desejada, e determina para cada SGDB a sequência de operações necessárias para ajustar a tabela para ela ficar com a definição da nova estrutura, através do cruzamento das estruturas. Campos existentes na estrutura antiga e não existentes na nova são removidos, campos existentes na nova e não existentes na antiga são criados, e campos existentes nas duas podem ter suas características alteradas. Apenas as trocas de tipo de “C” Caractere para “N” numérico e vice-versa suportam manter os dados nos campos.

Como funciona a transação no DBAccess ?

Cada SGSB homologado possui transacionamento atômico por instrução. Isto significa que, caso seja disparado uma execução SQL de um Update que afete várias linhas, se uma não pode ser alterada, nenhuma será. Quando precisamos garantir que várias operações em um bloco sejam completas em conjunto, usamos as instruções BEGIN TRANSACTION e END TRANSACTION do Advpl, onde todas as instruções executadas dentro deste bloco não vão fazer COMMIT das informações no SGDB, isto será feito apenas no END TRANSACTION. Se ocorrer algum erro durante o processo, entre o Begin e o End transaction, todas as operações feitas a partir do BEGIN TRANSACTION serão descartadas. Por baixo destas instruções existe uma implementação que depende do ambiente ERP Microsiga, isto é, o processo em execução precisa ser um programa do ERP chamado a partir do Menu, ou um Job que faça a inicialização do ambiente ERP usando por exemplo o comando PREPARE ENVIRONMENT ou a função RcpSetEnv(). Estes tratamentos também estão atrelados às funções RecLock() e MsUnlock() do Framework AdvPL do ERP Microsiga.

O DBAccess pode conectar com outros SGDBs ?

Sim, ele pode. Porém, esta conexão é feita via uma conexão ODBC genérica, que não permite a emulação ISAM. Praticamente qualquer ODBC que você possa registrar como fonte de dados de ODBC no Windows pode ser acessada. Usando a build mais atual do DBAccess, existe uma aba de configuração de ODBC genérica. Você pode estabelecer a conexão usando a função TClink(), informando o banco “ODBC/” mais o alias da fonte de dados cadastrada no Gerenciador de Fontes ODBC do sistema operacional. Com esta conexão, voce pode abrir Queries, que devem ser montadas de acordo com a capacidade e regras da ODBC utilzada, onde os dados retornados podem ser char/varchar ou numéricos, usando DbUseArea() com TcGenWry(), e pode executar instruções diretamente no SGDB através da função AdvPL TcSqlExec(). Isto pode ser muito útil para realizar integrações com outras fontes de dados.

Conclusão

Eu acho que com estes parágrafos, dá pra matar um pouco a curiosidade sobre o DBAccess e seu papel no acesso a dados do ERP Microsiga. Caso algúem tenha mais alguma pergunta a acrescentar sobre este assunto, insira a sua pergunta como um comentário deste post 😀 PAra dúvidas e sugestões de outros assuntos, me envie um e-mail com o assunto “BLOG” para siga0984@gmail.com 😀

Novamente, agradeço a audiência, e desejo a todos TERABYTES de sucesso 😉

Até o próximo post, pessoal 😀

Escalabilidade e Performance – Segredos

Introdução

Outo dia li um post muito interessante, onde o autor menciona alguns “segredos” para uma aplicação escalável, com algumas técnicas comuns utilizadas em aplicações WEB ( Vide post original nas referências no final do Post). Resolvi me basear nele para exemplificar o que cada um dos tópicos elencados poderia agregar ao sistema, e levantar algumas questões de aplicabilidade de cada um, dentro do ambiente AdvPL.

“STATELESS”

“Se você quer um sistema ou um serviço escalável, com certeza você quer que todas as requisições para este serviço sejam stateless.
Mas por que? Simplesmente por que caso em um futuro próximo você precise rodar a sua aplicação em um cluster, você não prende um cliente a um nó do cluster, cada requisição pode ir para o nó do cluster que estiver com a menor carga naquele momento, fazendo com que o tempo de resposta aquela requisição seja o menor possível, mantendo o nó do cluster que vai atender a esta requisição ocupado o menor tempo possível.” (Sobre Código: Os 5 segredos para um sistema altamente escalável, por Rodrigo Urubatan)

Esta afirmação casa com os princípios de escalabilidade e performance já mencionados em posts anteriores, mais especificamente sobre uma regra que diz “não estabeleça afinidade”. Basicamente, o “stateless” significa que uma requisição de processamento não deve depender de um estado específico de uma requisição anterior. Isto significa que o agente de processamento da requisição não deve reter nenhuma informação da requisição anterior, o que torna possível distribuir uma requisição de processamento para qualquer agente disponível no cluster.

Isto pode ser aplicado a diversos tipos de processamento, mas normalmente requer que a aplicação seja desenhada para trabalhar desta forma. Por exemplo, hoje quando desenvolvemos uma aplicação AdvPL para ser acessada através da interface do SmartClient, a aplicação trabalha com uma conexão TCP persistente, onde o programa AdvPL responsável pelas instruções de interface, também é responsável por montar o ambiente de execução e executar as aplicações de processamento e acesso a SGDB e meta-dados no mesmo processo.

Por exemplo, uma inclusão de um cliente através de um programa de interface SmartClient no AdvPL, é iniciada ao acionarmos um botão na janela, que executa uma função do código AdvPL pelo Application Server dentro do próprio processo, que acessa o SGDB e executa efetivamente a inserção e demais integrações e gatilhos sistêmicos relacionados (pontos de entrada do ERP), mantendo a interface em “espera” enquanto o processo é executado.

Para esta operação ser executada em um outro nó do cluster, a aplicação precisaria ser desenhada para, no momento de submeter a inclusão de um cliente, a função deveria gerar um request de inclusão de cliente, e despachá-la para um agente de distribuição de processos, que iria alocar um processo em espera no cluster de processamento, para este processo dedicado realizar o acesso ao banco e concluir a operação, liberando a interface para iniciar uma nova inclusão ou outra operação. A dificuldade de lidar com estes eventos é desenvolver um mecanismo resiliente, que permita gerar informações e um “BackLog” do que foi feito, pois procurar um erro de processamento ou comportamento em um ambiente assim, sem rastreabilidade das operações, não será uma tarefa fácil.

Um WebService por natureza é concebido como STATELESS. Existem algumas tecnologias que permitem criar afinidade e persistência em WebServices, porém isto foge ao objetivo principal da natureza das requisições e dos serviços que a implementação original se propõe a fazer. Se uma aplicação em WebServices precisa de afinidade e persistência, o uso de WebServices não parece uma boa escolha. Nem toda a operação pode ser totalmente assíncrona, mas muitas etapas de processo compensam o custo da transformação, revertida em escalabilidade.

“REQUEST RESPONSE TIME” (RRT)

Partindo de um ambiente de serviços distribuídos, onde vários processos podem realizar operações específicas, é fundamental que as requisições importantes ( ou prioritárias) sejam atendidas com o menor tempo de resposta possível. É o mesmo princípio dos caixas de um banco: Quando temos mais clientes do que caixas disponíveis, é formada uma fila, e o primeiro caixa que terminar o atendimento torna-se disponível e chama o primeiro da fila.

Se os caixas forem lentos, quando começar uma fila, as pessoas desta fila vão demorar para serem atendidas. Então, ou você coloca mais caixas, ou você melhora o desempenho dos caixas. Pensando por exemplo na priorização de atendimento a idosos, portadores de necessidades especiais, gestantes e mães com crianças de colo, são criadas duas filas de atendimento, vamos chamá-las de “normal” e “prioritária”. Todos os caixas podem atender a qualquer pessoa da fila, porém ocorre um escalonamento do atendimento.

Quanto mais rápido e eficiente for o atendimento de um caixa, mais clientes por hora ele será capaz de atender. A mesma regra vale para requisições de processamento (SOA/RPC/SOAP/REST). Se você tem um volume diário de X requisições, sujeitas a variações ou picos, e cada caixa aberto consegue atender em média N requisições por minuto, e você tem Y caixas abertos, se todas as X requisições chegarem ao mesmo tempo, as Y primeiras são atendidas imediatamente, e as demais entram na fila. Com todos os caixas atendendo, se ninguém mais entrar na fila, voce vai manter todos os caixas ocupados e trabalhando por M minutos até não ter mais ninguém na fila.

Pegamos o total de requisições (ou clientes) X , dividimos pelo numero de processos disponíveis (ou caixas abertos) Y, e temos uma média de quantas requisições devem ser processadas por cada processo (quantos atendimentos cada caixa deve fazer). Multiplicamos este número pelo tempo médio de processamento da requisição (tempo de atendimento), e teremos uma ideia de quanto tempo será necessário para eliminar a fila. Se chegam 20 requisições, e existem 4 processos disponíveis, cada um deles vai realizar 5 processamentos. Se cada processamento tem um tempo médio de 3 segundos, cada processo vai permanecer ocupado processando por 5×3 = 15 segundos. Se neste meio tempo não chegar mais ninguém na fila, em 15 segundos a fila acaba. Um caixa trabalhando sem parar em um minuto (60 segundos) , consegue atender (sem pausa ou intervalo) 60/3 = 20 requisições em um minuto. Como temos 4 processos, todos juntos conseguem atender 20 x 4 = 80 requisições por minuto.

Se dobrarmos o número de processos (8), conseguimos atender 160 requisições por minuto. Se o tempo de cada processamento (3 s.) diminuir pela metade (1,5 s.), conseguimos atender a 160 requisições por minuto com apenas 4 processos dedicados. Muitas vezes não temos como aumentar mais os processos, por limites de sistema ou esgotamento de recursos, então quanto mais leve e rápido for cada processo, melhor.

Usando AdvPL, existe flexibilidade em se criar pools de processos nativos, e dependendo de sua carga e consumo de memória, colocar múltiplos processos para atender requisições simultâneas. Porém, devem ser observados se os processos aderem aos princípios de paralelismo, senão a aplicação vai jogar memória fora e não vai escalar.

“CACHE”

Lembrando de uma das regras básicas de desempenho de tráfego de informações, buscar uma informação pela rede costuma ser mais lento que ler do disco, e pegar ela da memória é mais rápido do que ler do disco. Mas como não dá pra colocar tudo na memória, e estamos falando de paralelismo em sistemas distribuídos, usar um CACHE das informações mais repetidamente lidas na memória de cada máquina é uma forma bem eficiente de reduzir o RRT. Mas, lembre-se: Não é tudo que voce precisa colocar em um cache … apenas as informações mais acessadas, e com baixa volatilidade. Usar um cache local na memória do servidor, compartilhado pelos demais processos, pode economizar muitas idas e vindas de requisições pela rede.

Um exemplo disso se aplica mais facilmente a uma aplicação WEB dinâmica, onde uma página de promoções acessa o SGBD para mostrar os produtos em promoção. Se as promoções são alteradas diariamente, vale a pena fazer um cache dessa página, e removê-la do cache apenas quando houver alteração das promoções. Para um ERP, um cache interessante seria os meta-dados de algumas tabelas. Se boa parte dos usuários do sistema abre as mesmas tabelas e telas, a leitura destas definições poderiam ser colocadas em um cache na máquina dos slaves, alimentado sob demanda e com uma validade em tempo pré-determinada. O primeiro usuário que abre uma tela de cadastro de produtos ou pedidos alimenta o cache, e todos os demais usuários conectados em serviços naquela máquina pegam as definições do cache local, muito mais rápido, e sem consumir recurso de rede.

Existem meios de se criar caches em AdvPL, usando por exemplo variáveis globais, ou mesmo utilizar um cache de mercado (MemCacheDB, por exemplo), desde que seja escrito um Client em AdvPL que use a api client de Socket’s do Advpl (Classe tSocketClient) para fazer a comunicação. RPC e variáveis globais podem fazer uma bela dupla, mas vão precisar de um certo nível de controle e gerenciamento implementado manualmente, mas isto não inviabiliza esta alternativa.

“REMOTE DATA”

Quando falamos de aplicação Client-Server em Cluster, devemos ter em mente que as informações comuns a determinados processos precisam estar em um lugar onde todos os nós de processamento tenham acesso. Parte da premissa de não criar afinidade. Fica mais fácil citar um exemplo de servidor WEB com Upload de imagens, onde você grava a imagem em uma pasta do servidor: Ao invés de compartilhar esta pasta pelo sistema de arquivos, é possível criar um servidor dedicado a conteúdo estático, e fazer um mecanismo de cache ou réplica nos nós, se ou quando necessário.

A abordagem do AdvPL parte da premissa que cada serviço slave tenha acesso ao RootPath do ambiente, compartilhado pelo sistema operacional do equipamento. Definitivamente um excesso de acessos concorrentes pode prejudicar uma escalabilidade.

“REVERSE PROXY”

O exemplo de proxy reverso também se aplica mais em escalabilidade de ambientes WEB. Ele serve de “Front-End” da sua aplicação, permite a utilização de técnicas de Cache, mascaramento de IP, “esconde” a sua infra-estrutura interna, entre outas funcionalidades. O detalhe importante disso é que um Proxy Reverso, pelo fato de estar “na frente” de tudo, ele passa a ser um SPOF (Single Point of Failure). Se o Proxy Reverso “morrer”, sua aplicação morre junto.

Para aplicações SOA, uma alternativa interessante é usar o já mencionado “controlador” de requisições. Cada nó do cluster pergunta para um controlador de serviço onde está o nó mais próximo disponível, e cada serviço de controle fala com os demais. Assim, você pode deixar serviços ativos em vários nós, e caso um nó saia do ar, o controlador direciona a requisição para outro serviço disponível.

Resumo geral dos conceitos

Cada uma das técnicas ou “segredos” abordados exige que a aplicação seja desenvolvida para aderir a estes paradigmas. Uma aplicação Client-Server monolítica e de conexão persistente não se encaixaria neste modelo sem uma grande refatoração. É mais complicado gerenciar múltiplos recursos em múltiplos equipamentos, é mais complicado desenvolver pensando nestas características, a administração deste tipo de ambiente requer instrumentações, alertas e procedimentos da forma mais automatizada possível. Imagine você ter que conectar e abrir cada uma das máquinas para procurar por um LOG de erro específico, ou tentar descobrir por que ou como uma informação inconsistente foi parar na base de dados. Cada camada precisa estar “cercada” por mecanismos que visem minimizar inconsistências e evitar que elas se propaguem, além de permitir rastrear os caminhos da informação.

No AdvPL são fornecidos recursos como os WebServices (SOAP e REST), RPC nativo entre servidores, IPC entre processos da mesma instância de Application Server. A junção de todos eles pode tornar real e segura uma implementação desta natureza. Agrupando requisições por funcionalidade, e tendo um painel de gerenciamento e monitoramento dos recursos, você consegue medir quanto “custa” cada pedaço do sistema em consumo de recursos, e consegue lidar melhor com estimativas de crescimento, identificação de pontos críticos de melhoria, tornando assim possível a tão sonhada “escalabilidade horizontal” — em grande estilo.

Conclusão

A automatização de processos de Build e testes têm se mostrado muito efetiva em cenários de desenvolvimento e roll-out de produtos. Eu acredito que já esteja mais que na hora de criar mecanismos assistidos de deploy e mecanismos nativos de painéis de gestão de configuração e ambiente. Uma vez estabelecida a confiabilidade nos mecanismos de monitoramento, ações podem ser programadas e realizadas automaticamente, minimizando impactos e reduzindo os riscos de ter uma indisponibilidade total do ambiente computacional.

Criar uma aplicação que desde a sua concepção já considere estes pontos, será tão trabalhosa quando migrar uma aplicação que conta com comportamentos sistêmicos persistentes, mas ambos os esforços devem compensar o potencial de expansão que pode ser adquirido com esta abordagem.

Novamente, agradeço a audiência, e desejo a todos TERABYTES de sucesso 😀

Até o próximo post, pessoal 😉

Referências

Sobre Código: Os 5 segredos para um sistema altamente escalável, por Rodrigo Urubatan. Acessado em 06/12/2015 em <http://sobrecodigo.com/os-4-segredos-para-um-sistema-altamente-escalavel/>.

Stateless protocol. (2015, August 20). In Wikipedia, The Free Encyclopedia. Retrieved 01:33, October 25, 2015, from https://en.wikipedia.org/w/index.php?title=Stateless_protocol&oldid=677029705

Primeiro aniversário do “Tudo em AdvPL”

Em 21 de Novembro de 2015, o Blog “Tudo em AdvPL” completou um ano de existência, contados do primeiro “post”. Eu sou apaixonado por tecnologia e programação desde que eu entendi o conceito da palavra (e do “Byte”), e eu gostaria de compartilhar isso com o mundo, onde existem mais pessoas que, em diferentes graus e intensidades, também têm afinidade com este mundo mágico da Tecnologia da Informação. Depois de acompanhar de perto a evolução da Internet nos últimos 20 anos, decidi que estava mais que na hora de arregaçar as mangas e fazer algo a respeito.

Hoje só tenho a agradecer a vocês, leitores e visitantes do “Tudo em AdvPL”, que buscam por mais informações e conhecimentos, que comentam um post com elogios, dúvidas ou sugestões de abordagem de outros assuntos, e que compartilham com seus amigos nas redes sociais o conteúdo aqui disponível 😉

Mais uma vez, obrigado pela audiência, e desejo a todos TERABYTES de SUCESSO 😀

“Toda a grande caminhada começa com um pequeno passo” — BUDA

filme-06-020

“Viagem ao Oiapoque (2006), BR-156” – foto por Júlio Wittwer.