English readers and other languages: Many posts are in portuguese, you can use the Translate button at left side.

Clique nas imagens dos artigos! Elas levam você para o site do artista que a criou e muitas
vezes tem assuntos relacionados ou outras imagens para expandir seus horizontes!

sexta-feira, 12 de junho de 2009

Corrigindo Corrupção de Dados em arquivos DBF - Clipper, xHarbour, xBase, etc

Clipper - Corrupção de Dados

Desenvolvedores que utilizam a linguagem Clipper frequentemente vão se deparar com problema de corrupção de dados em arquivos DBF e/ou nos índices.
Descartando os problemas que possam ser eventualmente causados por falhas de equipamento, cabos, placas, HD com defeito, etc, na ampla maioria das vezes, estes problemas são totalmente contornáveis, bastando ao programador, adotar medidas preventivas no seu programa.
Tratamento de erros é algo que todo bom programador deve adotar se quiser apresentar sistemas confiáveis para o usuário.
A solução abordada também é válida para Foxpro, xBase++, xHarbour, etc
A lógica aqui apresentada, serve também como modelo para linguagens de outras categorias, pois trata-se de princípios universais a serem observados.
Em tempo, também podem ocorrer problemas de perdas de dados por causa do tamanho dos arquivos. O DBF possui limitações de tamanho, que varia um pouco, mas geralmente ao redor máximo de 1Gb. Neste caso, você terá que adotar um gerenciador diferente para seus dados.
Para os usuários de DBF, que não queiram, ou não precisam reprojetar imediatamente seus dados para outro formato, como SQL, recomendo o ADS Advantage Database Server, excelente gerenciador client/server da Sybase. É altamente performante, agrega muita segurança ao processamento e é uma boa opção para grandes volumes de dados. E também, já é uma porta para quem estiver pensando em migrar para SQL.

Vamos lá então:

-----------------------------------------------------------
Impedindo Erros de Gravação em Clipper

Principais Erros:
* Corruption Detect
* Internal Error 19
Uma das principais causas de corrupção de dados ocorre ocorre porque nem sempre o LOCK é bem sucedido, devido a demora na rede, ou porque o registro está bloqueado noutra estação.
Este código testa se o lock foi bem sucedido, senão, faz um loop padrão de N-vezes ou até o limite solicitado.
Se ainda não conseguir, vai apresentar uma mensagem na tela avisando que está a espera de liberação, a qual o usuário pode interromper por ESC.
A rotina aceita um parâmetro para especificar quanto tempo aguardar.
Adaptem o código ao seu caso:
Desenvolvido em Clipper 5.2e
Cabeçalho:
#command default <variable1> to <value1> [, <variableN> to <valueN> ] => ;
if <variable1> == nil; <variable1> := <value1>; endif;
[; if <variableN> == nil; <variableN> := <valueN>; endif ]
// Código desenvolvido por Gilberto Strapazon
//
Function Exemplo
//
// Exemplo de uso da função NET_REG
if .not. Arquivo->(dbseek(chave))
Arquivo->(dbappend())

...(seu código aqui) gerar chave, etc...
endif
if .not. net_reg()
mensagem("Nao foi possivel incluir registro no arquivo",, 0)
return false
endif
Replace Arquivo->campo1 with OutroArquivo->campo1,;
Arquivo->campo2 with OutroArquivo->campo2
Arquivo->(dbunlock())
Arquivo->(dbcommit())
Return true
Function NET_REG(limite)
local savtela
local xvezes
local msgaviso
local windx
local wcontador
default limite to 0 // se limite > 0, aguarda N segundos e volta
// se limite == 0 fica aguardando
CLEAR TYPEAHEAD
savtela := savescreen(0, 0, maxrow(), maxcol())
savcolor := setcolor()
xvezes := 0
wcontador := 0
msgaviso := "Aguardando para gravar registro no arquivo " +
alltrim(alias(select()))
do while true
if Rlock() // Se conseguir bloquear o registro
restscreen(0, 0, maxrow(), maxcol(), savtela)
return true // Retornar...
endif
//
if (xvezes < 6)
xvezes++
inkey(0.5)
loop
endif
aguarde(msgaviso) \\ janela padrão de Aguarde
mensagem(msgaviso) \\ rotina padrão de mensagem rodapé
@ maxrow()-1,00 say padc(msgaviso + ". Tecle ESC para interromper")
if inkey(0.5) = K_ESC // aguarda 0.5 segundo
setcolor(savcolor)
restscreen(0, 0, maxrow(), maxcol(), savtela)
return false
endif
wContador++
if limite > 0 .and. ; // se for informado limite
wContador > limite // aguarda o tempo especificado
restscreen(0, 0, maxrow(), maxcol(), savtela)
return false // aviso de erro. Nao bloqueou
endif
//
enddo
restscreen(0, 0, maxrow(), maxcol(), savtela)
return(true)
Function mensagem(vMsg, vJust, vtempo, vLinha, vTom)
// Apresenta mensagem padrao no rodape da tela ou na linha informada
// Se for informado TEMPO, faz pausa pelo tempo especificado
// Se for informado TOM, soa um sinal.
local savcolor
public cRealce := "W+/R,N/W,,,W+/R"
default vMsg to ""
default vJust to "E"
default vTempo to nil
default vLinha to maxrow()
default vTom to false
savcolor := setcolor()
vJust := upper(vJust) // padroniza parametro
if empty(vMsg)
setcolor("GR+/B")
else
setcolor(m->cRealce)
endif
do case
case vJust = "E"
@ vLinha, 0 say padr(vMsg, maxcol()+1)
case vJust = "C"
@ vLinha, 0 say padc(vMsg, maxcol()+1)
case vJust = "D"
@ vLinha, 0 say padl(vMsg, maxcol()+1)
endcase
if vTom
tone(440,1)
endif
if vTempo <> NIL
inkey(vTempo)
endif
setcolor(savcolor)
return
Function Aguarde(mensagem, linha, cor)
// Mostra mensagem hh:mm:ss aguarde...
//
local wcoli
local wlinf
local wcolf
local tammsg := 0
local savcolor
public cRealce := "W+/R,N/W,,,W+/R"
default linha to (maxrow()/2)-3
default cor to m->cRealce
savcolor := setcolor()
setcolor(m->cRealce)
mensagem := time() + " " + alltrim(mensagem)
tammsg := (maxcol() - (len(alltrim(mensagem)))) / 2
wlinf := linha + 3
wcoli := tammsg - 2
wcolf := (maxcol() - tammsg) + 1
janela(linha, wcoli, wlinf, wcolf, mensagem,, false, cor)
@ linha +2, wcoli+ 2 say mensagem
setcolor(savcolor)
return(NIL)
==================================================================

Sem comentários: