Página 1 de 2

Como testar a integridade de arquivo .MEM?

Enviado: 23 Jan 2015 11:07
por clodoaldomonteiro
Olá amigos,

Tem um erro contumaz que ocorre com meus clientes, que é a quebra do arquivo .MEM, e geralmente ocorre quando há uma queda de energia que de alguma forma grava o arquivo .MEM de forma errada.

Pergunto:
1- Se quando abrimos um arquivo .MEM com o comando REST, este arquivo permanece aberto ou se somente ele ler ar variáveis que estão dentro do arquivo e encerra a conexão com o arquivo .MEM?
2 - Tem como fazer-se um teste de credibilidade de um arquivo .MEM, pois daí poderíamos antecipar uma série de comandos a fim de não passarmos o erro para o cliente final?

Att.
Clodoaldo Monteiro

Como testar a integridade de arquivo .MEM?

Enviado: 23 Jan 2015 11:15
por Kapiaba

Código: Selecionar todos

   A:=4

   NOME:="JOAO"

   SAVE TO ARQVAR// salva todas as variáveis de memória

   // no arquivo ARQVAR.MEM
   RELEASE ALL // apaga todas as variáveis

   RESTORE FROM ARQVAR // restaura as variáveis do arquivo ARQVAR.MEM

   ? A
   ? NOME

http://underpop.free.fr/c/clipper/comandos-clipper.pdf

abs.

Como testar a integridade de arquivo .MEM?

Enviado: 23 Jan 2015 12:34
por Jairo Maia
Olá Clodoaldo,
clodoaldomonteiro escreveu:Tem um erro contumaz que ocorre com meus clientes
Estranho é ser costumaz. Já passei por isso, mas muito e muito raramente (3 a 4 vezes acho), e todas as vezes foi após queda de energia, o que significa que coincidiu de ser no momento que o arquivo Mem estava sendo gravado.
clodoaldomonteiro escreveu:1- Se quando abrimos um arquivo .MEM com o comando REST, este arquivo permanece aberto ou se somente ele ler ar variáveis que estão dentro do arquivo e encerra a conexão com o arquivo .MEM?
Apenas lê e fecha o arquivo. Podemos provar isso apagando o arquivo que foi lido em seguida, o que significa que foi fechado (liberado).

Quanto a fazer o teste de integridade, veja se o exemplo abaixo ajuda:

Código: Selecionar todos

Function Main()
 
 Private xMemVar1 := "ABCDE"
 Private xMemVar2 := 10.00
 Private xMemVar3 := Date()
 Private xMemVar4 := .T.
 
 Hb_MVSave( "ArqMem.Mem", "xMemVar*" )  // em Harbour, se extensao omitida sera .HBV
 
 /*
   Quando for restaurar o arquivo Mem, melhor apagar as variaveis que
   se pretende recuperar, garantindo que elas serão as variaveis do arquivo
   em caso de falha, ou seja, nao herdar alguma anterior:
 */
 Release All Like xMemVar*
 
 Hb_MVRestore( "ArqMem.Mem", .T. )  // vamos recarregar as variaveis
 
 //Release xMemvar4  // se descomentar essa linha por exemplo, simula o erro
 
 If Type( "xMemVar1" ) = "U" .Or. ValType( xMemVar1 ) = "U" .Or. ;
    Type( "xMemVar2" ) = "U" .Or. ValType( xMemVar2 ) = "U" .Or. ;
    Type( "xMemVar3" ) = "U" .Or. ValType( xMemVar3 ) = "U" .Or. ;
    Type( "xMemVar4" ) = "U" .Or. ValType( xMemVar4 ) = "U"
  
  Hb_Alert( "Arquivo ArqMem.Mem Corrompido!" )
 
 Else

  Clear Screen
  ? "xMemVar1: ", xMemVar1
  ? "xMemVar2: ", xMemVar2
  ? "xMemVar3: ", xMemVar3
  ? "xMemVar4: ", xMemVar4
  ?
  
 EndIf

Return Nil

Como testar a integridade de arquivo .MEM?

Enviado: 23 Jan 2015 13:35
por Pablo César
Oi Clodoaldo,

Acho que você poderia ver qual é a mensagem de erro quando ocorre fragmentação no arquivo MEM e atrevo-me a dizer que você poderia tentar corrigir apagando-o quando este der esse erro. Terá que fazê-lo mediante o GETSYS.prg (ao menos no Clipper era o responsável pelos tratamento de erros).
Uma vez deletado, no seu programa, faça a verificação de existência, caso não exista, crie-o novamente com a variaveis default.

Aqui tem um código que poderia te servir para você acessa em baixo nivel:

Código: Selecionar todos

nMemHandle := Fopen( 'Errormem.mem', 2 )
nMemLength := Fseek( nMemHandle, 0, 2)
Fseek(nMemHandle,0)
nCount := 1
Do While Fseek(nMemHandle, 0, 1)+1 < nMemLength
   nMemWidth:= space(18)
   Fread( nMemHandle, @nMemWidth, 18 )
   cVarName := Left( nMemWidth, At( Chr(0) , nMemWidth ) -1 )
   cVartype := Substr( nMemWidth, 12, 1 )
   cVarRec  := Bin2w( Right( nMemWidth, 2 ) )
   nMemCount:= If( cVarType $ Chr(195)+Chr(204), 14+cVarRec, 22 )
   Fseek(nMemHandle, nMemCount, 1)
   cTemp    := Left(cVarName + Space(10), 10)
   cTemp    += ' Tipo ' + Type(cVarName)
   IF "TELA" $ ALLTRIM(cVarName)
      cTemp    += ' < Tela > '
   ELSE
      cTemp    += ' ' + If( Type(cVarName) == 'C', ['] + &cVarName + ['], StrValue( &cVarName ))
   ENDIF
   nBytes   := 0
   Do Case
      Case Type(cVarName) == 'C'
           nBytes += ( nLenTemp := Len( &cVarName. ) )
      Case Type(cVarName) == 'N'
           nBytes += ( nLenTemp := 9 )
      Case Type(cVarName) == 'L'
           nBytes += ( nLenTemp := 2 )
      Case Type(cVarName) == 'D'
           nBytes += ( nLenTemp := 9 )
   EndCase
   Fwrite(     nFhandle, Transform(nLenTemp, '9999999') + ' Bytes -> ')
   FWriteLine( nFhandle, cTemp )
EndDo
Fclose( nMemHandle )
Ferase( 'Errormem.mem' )
Fclose( nFhandle )
No Harbour, tem o código fonte em: https://github.com/harbour/core/blob/ma ... /memvars.c
Eu estou deixando de usar esse tipo de arquivo. Em lugar disso eu utilizo o arquivo INI.

Como testar a integridade de arquivo .MEM?

Enviado: 24 Jan 2015 04:24
por rochinha
Amiguinhos,

Clodoaldo?

Voce se lembra deste tópico

Como testar a integridade de arquivo .MEM?

Enviado: 31 Jan 2015 12:31
por clodoaldomonteiro
rochinha escreveu:Amiguinhos,

Clodoaldo?

Voce se lembra deste tópico
Rochinha, agora lembrei do tópico antigo, vou estudar melhor sua solução, mas ela parece que para tratamento de array e no meu caso são variáveis mesmo.
Pablo César escreveu:Oi Clodoaldo,

Acho que você poderia ver qual é a mensagem de erro quando ocorre fragmentação no arquivo MEM e atrevo-me a dizer que você poderia tentar corrigir apagando-o quando este der esse erro. Terá que fazê-lo mediante o GETSYS.prg (ao menos no Clipper era o responsável pelos tratamento de erros).
Uma vez deletado, no seu programa, faça a verificação de existência, caso não exista, crie-o novamente com a variaveis default.


Pablo,
Eu acho que os tratamentos de erros ficam em ERRORSYS ou coisa assim.
Se eu usar o Fopen() para abrir o arquivo, com certeza não terá erro de abertura, pois o arquivo existe, só que está corrompido segundo os padrões .MEM.

Queria saber mesmo é se tem alguma função que verifique sem um arquivo .MEM está hápto a ser aberto pelo comando RESTORE, o fOpen(), por exemplo, retorna um erro e assim posso tratá-lo.
Jairo Maia escreveu:Olá Clodoaldo,

Estranho é ser costumaz. Já passei por isso, mas muito e muito raramente (3 a 4 vezes acho), e todas as vezes foi após queda de energia, o que significa que coincidiu de ser no momento que o arquivo Mem estava sendo gravado.
Jairo, digo que é contumaz, porque tenho uns 50 clientes no interior do Piauí e realmente tem muito problema de queda de energia, mas o que eu queria mesmo era,, por exemplo, testar quantas variáveis tem dentro do arquivo, isso antes de abrir ele com o comando RESTORE.
Kapiaba escreveu:

Código: Selecionar todos

   A:=4

   NOME:="JOAO"

   SAVE TO ARQVAR// salva todas as variáveis de memória

   // no arquivo ARQVAR.MEM
   RELEASE ALL // apaga todas as variáveis

   RESTORE FROM ARQVAR // restaura as variáveis do arquivo ARQVAR.MEM

   ? A
   ? NOME

http://underpop.free.fr/c/clipper/comandos-clipper.pdf

abs.
Kapiaba, eu já sei abrir o arquivo e o que quero mesmo é testá-lo antes de abrir.

Fico grato pela atenção de todos.

Como testar a integridade de arquivo .MEM?

Enviado: 31 Jan 2015 12:46
por clodoaldomonteiro
Pessoal, o erro que acontece é esse:
Imagem
Abraços.

Como testar a integridade de arquivo .MEM?

Enviado: 31 Jan 2015 13:44
por rochinha
Amiguinho,

Verifique se nas variaveis que você está guardando se algum caracter indevido esteja sendo armazenado.

Como testar a integridade de arquivo .MEM?

Enviado: 31 Jan 2015 13:49
por Jairo Maia
Olá Clodoaldo,

Agora que vi que você usa xHarbour. O exemplo que passei funciona apenas no Harbour, e a função Hb_MvRestore() não causa esse erro mesmo que você teste abrindo um arquivo qualquer, apenas não carrega as variáveis. Por isso é possível testar da forma que passei. No entanto, como o xHarbour passou por várias atualizações, será que estas funções não foram compatibilizadas?

Como testar a integridade de arquivo .MEM?

Enviado: 31 Jan 2015 17:57
por clodoaldomonteiro
Olá,
rochinha escreveu:Amiguinho,

Verifique se nas variaveis que você está guardando se algum caracter indevido esteja sendo armazenado.
Rochinha,
Vi em um arquivo .MEM "quebrado" que é como se os caracteres separadores dos campos não estivessem completos ou algum nome de variável faltando.
Jairo Maia escreveu:Olá Clodoaldo,

Agora que vi que você usa xHarbour. O exemplo que passei funciona apenas no Harbour, e a função Hb_MvRestore() não causa esse erro mesmo que você teste abrindo um arquivo qualquer, apenas não carrega as variáveis. Por isso é possível testar da forma que passei. No entanto, como o xHarbour passou por várias atualizações, será que estas funções não foram compatibilizadas?
Jairo,
É, uso o xHarbour 1.0, pois não consegui converter minha aplicação para o Harbour 3.0. É que estou usando a GTWVW, onde uso menus Windows com telas Console.
Vou verificar se existe a função que você indicou.

Obrigado a todos.

Como testar a integridade de arquivo .MEM?

Enviado: 31 Jan 2015 18:04
por clodoaldomonteiro
Tentei chamar o Comando RESTORE dentro de um Try:

Código: Selecionar todos

      Try
         REST FROM ( arqconf ) ADDI                                // restaura configuracoes gravadas
      Catch
         FErase( arqconf )
         ? 'Falha na abertura do arquivo de Configura‡äes.'
         Wait 'Tente entrar no sistema novamente.'
         Quit
      End
Mas não deu certo também.

Como testar a integridade de arquivo .MEM?

Enviado: 31 Jan 2015 18:32
por Pablo César
Então Clodoaldo, depois de você ter tentado abrir e não conseguiu, porque o MEM está corrompido, após o teu TRY basta verificar se tais varíáveis tem valor Nil e aí entaõ você as grava no MEM novamente.

Como testar a integridade de arquivo .MEM?

Enviado: 02 Fev 2015 14:45
por clodoaldomonteiro
Pablo...

Fiz um teste para ver a execução do Try, como está abaixo :

Código: Selecionar todos

Try
   Wait 1
   RESTORE FROM ( arqconf ) ADDI                // restaura configuracoes gravadas
   Wait 2
Catch
   FErase( arqconf )
   ? 'Falha na abertura do arquivo de Configura‡äes.'
   Wait 'Tente entrar no sistema novamente.'
   Quit
End
e vi que o sistema mostra o primeiro WAIT, e logo depois tenta fazer o RESTORE e mostrado a mensagem de erro que postei aqui, sendo assim, não temo eu tratar o erro, não é como uma função, que retorna alguma coisa para podermos ver o resultado.

Grato pela atenção.

Como testar a integridade de arquivo .MEM?

Enviado: 02 Fev 2015 19:24
por Pablo César
clodoaldomonteiro escreveu:não temo eu tratar o erro, não é como uma função, que retorna alguma coisa para podermos ver o resultado.
Você não entendeu o que eu quis dizer.
Pablo César escreveu:após o teu TRY basta verificar se tais varíáveis tem valor Nil e aí entaõ você as grava no MEM novamente.
Eu me equivoquei quando eu disse: "se tais varíáveis tem valor Nil" na verdade você verifica se existem com ValType.

Veja este exemplo:

Código: Selecionar todos

Function Main()
Local arqconf:="Clientes.mem", lErro:=.F.
Local CLI_NOME, CLI_NASCEU, CLI_SEXO

If !File(arqconf)
   CLI_NOME:="Clodoaldo"
   CLI_NASCEU:=DATE()-(365*30)
   CLI_SEXO:="MASCULINO"
   SAVE TO CLIENTES ALL LIKE CLI_*
   RELEASE ALL LIKE CLI_*
Endif

nMemHandle := Fopen( arqconf, 2 )
Fseek(nMemHandle,0)
Fwrite(nMemHandle,Chr(1)+Chr(2)+"Queda de Luz")
Fclose( nMemHandle )

BEGIN SEQUENCE
   Restore from ( arqconf ) Additive
RECOVER USING oError
   FErase( arqconf )
   ? 'Falha na abertura do arquivo de Configurações. ('+(oError:Description)+")"
   Inkey(0)
   // Quit
END

If ValType(CLI_NOME) = "U"
   CLI_NOME:="Clodoaldo"
   lErro:=.T.
Endif
If ValType(CLI_NASCEU) = "U"
   CLI_NASCEU:=DATE()-(365*30)
   lErro:=.T.
Endif
If ValType(CLI_SEXO) = "U"
   CLI_SEXO:="MASCULINO"
   lErro:=.T.
Endif
If lErro .or. !File(arqconf)
   SAVE TO CLIENTES ALL LIKE CLI_*
Endif
? CLI_NOME
? DToC(CLI_NASCEU)
? CLI_SEXO
Return Nil
Substitua o BEGIN SEQUENCE por Try e RECOVER USING oError por Catch para que funcione em xHarbour.

Na minha opinião, você tendo os nomes e o valor default de cada variável, fica fácil você ver se carregou ou não.

Só que eu não consegui reproduzir o mesmo erro. Podia er sido muito bom você ter anexado o arquivo corrupto.

Aqui tem um tópico que fala de "Restore failed, unsupported type: 65408 for":
https://pctoledo.org/forum/viewto ... 853#p50853

Na minha opinião, você não precisava dar um QUIT quando ocorre o erro. Você teria duas opções válidas: mostrar o erro ou simplesmente omiti-lo. Ao omitir o erro você deleta o arquivo e cria novamente. Funções de baixo nível poderia ajudar a recuperar al, mas acho que não valeria a pena.

Como testar a integridade de arquivo .MEM?

Enviado: 05 Fev 2015 13:29
por Jairo Maia
Olá Pablo,

Permita-me apenas para registro o seguinte:

Para saber se uma variavel existe, a função é:

Código: Selecionar todos

Type( "VariavelEntreAspas" )  // verifica se determinada variável existe
Precisa ser entre aspas, ou seja, passada a função Type() como string, afinal a idéia é saber se existe alguma variável com esse nome.

Para saber o tipo do conteúdo de uma variável, a função é:

Código: Selecionar todos

ValType( VariavelSemAspas )  // verifica o tipo do conteúdo da variavel
Não pode ter aspas, e a variável necessariamente precisa existir, ou se tem o RTE: Variável não existe. Neste caso não haverá erro se colocar entre aspas, porém, sempre retornará type = "C", pois o conteúdo é string.

Penso então que em casos onde esse tipo de verificação seja necessário, podemos concatenar ambas dessa forma, e claro, nesta ordem:

Código: Selecionar todos

If Type( "xVariavel" ) = "U" .Or. ValType( xVariavel ) = "U"
 alert( "variável inexistente ou com conteúdo Nulo" )
EndIf
Ou se preferir identicar exatamente a situação de determinada variável, podemos fazer assim:

Código: Selecionar todos

If Type( "xVariavel" ) = "U"
 alert( "variável inexistente" )
ElseIf ValType( xVariavel ) = "U"
 alert( "variável com conteúdo Nulo" )
EndIf