Manipulação de arquivos em AdvPL – Parte 02

Introdução

No post anterior, Manipulação de arquivos em AdvPL – Parte 01, vimos em detalhes os comportamentos das funções de baixo nível de arquivo, acompanhados de um exemplo de manipulação simples de um arquivo texto. Neste post, vamos rever alguns detalhes, e ver como as funções de baixo nível de arquivo do AdvPL foram adaptadas para o Linux e MAC OS.

Vale a pena lembrar de novo

  • As funções FCreate() e FOpen() retornam um identificador numérico, chamado de Handler do arquivo. Ele é usado como parâmetro para as demais funções. Se o número retornado for -1 (menos um), isto indica uma falha na criação e/ou abertura da tabela, respectivamente.
  • Caso o nome do arquivo informado inicie com uma unidade de disco, o Application Server assume que o arquivo está na estação onde o SmartClient está sendo executado. Se você criou um JOB — processo sem interface — este JOB somente consegue abrir arquivos a partir do RootPath do ambiente no Protheus Server, onde o path deve começar com uma “\” barra inversa.

Novas informações

  • Um Handler de arquivo no AdvPL não pode ser compartilhado entre processos. Isto é, o handler retornado na criação ou abertura da tabela é válido apenas dentro do processo (ou Thread) que obteve o Handler.
  • Um Handler de arquivo válido obtido pelas funções FCreate() e/ou FOpen() mantém o arquivo aberto até que ele seja explicitamente fechado pela função FClose(). Após fechar o arquivo, este Handler deve ser descartado, pois ene não é mais válido após o fechamento da tabela.
  • Um Handler de arquivo não fechado explicitamente pelo programa AdvPL somente será fechado automaticamente pelo Application Server no término do processo / Thread — Seja ela finalizada com sucesso ou com erro de execução.

Comportamentos em ambientes Multi-Plataforma

Atualmente o Application Server é homologado para Windows e Linux, e o SmartClient é homologado para Windows, Linux e Mac OS. Porém, o sistema de arquivos destes sistemas operacionais difere em alguns pontos em relação ao Windows.

  • Não existe o conceito ou a implementação de letras para designar unidades de disco.
  • A barra separadoras de diretórios utilizada é a barra para a direita “/”, enquanto no Windows é usada a barra para a esquerda “\”.
  • O nome dos arquivos é case-sensitive. Isto é, chamou o arquivo de “Jose.txt”, e tentou abrir como “jose.TXT”, o sistema operacional retorna erro de “Arquivo não encontrado.”
  • O sistema de arquivos no Linux não prevê o tratamento de acesso exclusivo a um determinado arquivo por um determinado processo.
  • O compartilhamento de arquivos via rede é feito utilizando NFS, diferente do compartilhamento de arquivos do Windows, Você não tem nenhum prefixo ou identificador informando que seu arquivo está sendo acessado pela rede. O caminho do arquivo é escrito da mesma forma, porém a partir da pasta que deve ser acessada pela rede,deve ser feito no Linux e MAC OS um “ponto de montagem”, que indica ao sistema operacional que a partir daquela pasta, os arquivos estão fisicamente em outra máquina.

Devido a estas diferenças, foram adotadas algumas convenções para o sistema de arquivos do AdvPL no Linux.

  • Todos os arquivos do ambiente, a partir do RootPath, devem estar em capitulação baixa — isto é, em letras minúsculas — tanto no nome como na extensão, inclusive todas as pastas e/ou diretórios do ambiente devem estar com letras minúsculas. Mesmo que o seu fonte AdvPL passe como parâmetro para as funções de arquivo um nome com letras maiúsculas, internamente ele será convertido para minúsculas caso a plataforma seja Unix-Like (Linux).
  • No caso de utilização de serviços de Application Server em máquinas diferentes, para balanceamento de carga, por exemplo, o nome do RootPath do ambiente deve ser o mesmo para todas as instâncias, em todas as máquinas. Por exemplo, na máquina onde são gravados os arquivos  dentro o RootPath do ambiente, o RootPath é “/totvs/protheus12/envtop”. Este deve ser também o RootPath do ambiente em outras máquinas. A diferença para uma máquina “Slave” é que a pasta “envtop” vai existir como um ponto de montagem Client de compartilhamento de rede NFS (Network File System), que aponta para a pasta “/totvs/protheus12/envtop” da máquina principal.
  • No caso da utilização de mais de um serviço do Protheus compartilhando o mesmo RootPath de ambiente, mesmo que estes serviços estejam na mesma máquina, ‘é necessário haver a configuração de um “LockServer Protheus” — Configurar um serviço dedicado a obtenção de bloqueios exclusivos (Locks() para criação e abertura de arquivos, onde todos os Serviços de Protheus que acessam este RootPath devem apontar para um único LockServer.
  • A necessidade de uso de um Application Server Protheus configurado como LockServer no Linux existe para justamente emular o controle de acesso exclusivo a arquivos, que o Linux não possui nativamente, mas vários programas em AdvPL contam com este comportamento.
  • Mesmo que em Linux eu não tenha o conceito de “unidade de disco”, a forma de eu indicar que um arquivo deve ser aberto pelo SmartClient continua a mesma — informar uma unidade de disco no path do arquivo a ser acessado. Caso o SmartClient em uso seja Linux ou Mac OS, a unidade de disco informada será ignorada, e o arquivo será localizado pelo path e nome informados.
  • Mesmo que você tenha escrito o seu programa AdvPL usando as barras separadoras de arquivo para a esquerda “\”, as funções básicas da linguagem que realizam acesso a disco foram preparadas para converter automaticamente para “/”  caso a plataforma em uso seja Unix-like (como Linux e MAC OS).
  • Caso exista alguma diferença não tratada, ou seja necessário um tratamento diferenciado durante a execução de uma aplicação AdvPL, onde exista mudança ou indisponibilidade do recurso em algum sistema operacional ou plataforma, existem funções de diagnóstico no AdvPL que retornam por exemplo se o Application Server é Linux ou Windows, e qual é o SmartClient que está sendo usado — Linux, Windows ou MAX OS. Veja informações adicionais das referências, no final do post.
  • A lista de códigos de erro da função FError() possui uma numeração própria, diferente dos códigos de erro de manipulação de arquivos do Sistema Operacional em questão. Essa lista está documentada na própria função FError() na TDN.

Fonte de Testes

No post anterior, para cada função testada foi feita uma parte de um código, realizando as operações em sequência. Veja abaixo o fonte de testes e demonstração das funções de baixo nível de arquivo unificado — fonte tstfile.prw

#include 'protheus.ch'
#include 'fileio.ch'

USER Function TSTFILE()
Local nHnd 
Local cFile := '\temp\teste.txt'
Local cLine , nTamFile
Local cNewLine , nRead, nWrote

// Cria o arquivo 
// Automaticamente o arquivo é aberto em modo exclusivo para gravação
nHnd := fCreate(cFile)

If nHnd == -1
  MsgStop("Falha ao criar arquivo ["+cFile+"]","FERROR "+cValToChar(fError()))
  Return
Endif

// Cria uma linha em memória
cLine := "Olá sistema de arquivos" + CRLF

// Grava três linhas iguais, com 25 bytes cada 
fWrite(nHnd,cLine)
fWrite(nHnd,cLine)
fWrite(nHnd,cLine)

// Fecha o arquivo 
fClose(nHnd)

// Abre novamente para leitura e ecrita em modo exclusivo 
nHnd := fOpen(cFile,FO_READWRITE + FO_EXCLUSIVE )
If nHnd == -1
  MsgStop("Falha ao abrir ["+cFile+"]","Ferror " + cValToChar(fError()) )
  Return
Endif

// Identifica o tamanho do arquivo 
nTamFile := fSeek(nHnd,0,FS_END)
fSeek(nHnd,0,FS_SET)

conout("Tamanho do Arquivo = "+cValToChaR(nTamFile)+" byte(s)." )

// Lê a primeira linha do arquivo 
cBuffer := ""
nRead := FRead( nHnd, @cBuffer, 25 )
conout("Byte(s) lido(s) : "+cValToChar(nRead))

If nRead < 25
  MsgStop("Falha na leitura da primeira linha.","Ferror "+cValToChar(ferror()))
  Return
Endif

// Agora vamos trocar a segunda linha 
cNewLine := replicate('-',23)

nWrote := fWrite(nHnd , cNewLine )
conout("Byte(s) gravado(s) : "+cValToChar(nWrote))

If nWrote < 23
  MsgStop("Falha na gravação da segunda linha.","Ferror "+cValToChar(ferror()))
  Return
Endif

// fecha o arquivo 
fClose(nHnd)

Return

Este fonte está disponível para download no GITHUB.

Conclusão

Com este post, passamos a abranger praticamente todos os detalhes da implementação de baixo nível de arquivos do AdvPL. Ainda não testei este fonte no Linux, porém dada a natureza da implementação, o comportamento esperado é o mesmo.

Novamente agradeço a audiência, e desejo a todos TERABYTES DE SUCESSO 😀

Referências

 

 

 

 

 

 

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s