Página 1 de 1

Hard commit ou algo assim

Enviado: 26 Ago 2014 09:55
por JoséQuintas
Ainda estou mexendo naquele aplicativo Clipper Summer, passando pra Harbour.
Tem uma coisa nele que acho péssimo pra programação, mas estou na dúvida sobre vantagem do uso.

Os arquivos são abertos/fechados muitas vezes durante o fonte.
Pensava que era por causa de limite de arquivos abertos, mas limita a um máximo de uns 5 arquivos abertos, somente aonde necessário.
Num caixa, por exemplo, a cada lançamento os arquivos são abertos/fechados.

É ambiente de rede, servidor com nobreak.
Mas no caixa se desligar o terminal, acabar a luz, ou coisa assim, só se perde o lançamento atual.
Se deixar os arquivos abertos, como depende do cache do sistema operacional, qualquer coisa pode se perder.
Muito mais seguro apenas se limitar ao último lançamento, ficando parecido com um SQL no que se refere a situação do terminal se desligar, ou ficar sem energia elétrica.

Mas trabalhar num fonte onde um arquivo pode ou não estar aberto é trabalhoso demais e perigoso.
Tem algo no Harbour que permita fazer esse "hard commit", pra salvar tudo pendente?

Alternativas que imaginei:
- Salvar/restaurar arquivo,índices,ordem e recno pra poder fechar e reabrir
- Usar uma única área pra abrir/fechar os mesmos arquivos nos append/replace - opção talvez mais interessante

exemplo da segunda alternativa:

Código: Selecionar todos

AbreArquivos( { "arquivo1", "arquivo2", "arquivo3" } )
...
...
nSelect := Select()
SELECT 0
USE arquivo2 ALIAS savedata
SET INDEX TO arquivo2
REPLACE 
USE
SELECT ( nSelectAnt )
Tem alguma coisa no Harbour que já garanta salvar tudo?

Obs.
É engraçado, mas como justificar a mudança de fonte para o que é certo, se do jeito atual pode-se perder apenas o último lançamento, mas se ficar em cache, pode-se perder qualquer coisa, um bloco com informações aleatórias.

Hard commit ou algo assim

Enviado: 26 Ago 2014 10:06
por Jairo Maia
Jose, não seria isso que você quer?:

DbCommitAll() // Salva em disco todos os dados pendentes de todas as áreas abertas.
Description:
The DbCommitAll() function writes buffers of all work areas to disk. It performs the same operations as DbCommit(), except that all work areas with open databases are iterated in one function call.
Uso DbCommitAll() a cada final de lançamento, antes de enviar a impressora. Penso que é isso que você busca.

Hard commit ou algo assim

Enviado: 29 Ago 2014 15:20
por vilian
Jose,

O DbCommitAll() não funciona, não garante de fato a atualização física dos arquivos e índices. Se usar o ADS (Advantage Database Server) utilize o AdsWriteAllRecords().

Hard commit ou algo assim

Enviado: 29 Ago 2014 15:49
por janio
DbCommitAll() não funciona???

Taí uma baita novidade pra mim

Hard commit ou algo assim

Enviado: 29 Ago 2014 17:14
por vilian
Janio,

Tive a mesma surpresa que vc quando descobri isso. Mas é verdade, e é bem fácil de vc constatar - Inclua um lançamento, execute o DbCommitAll() e logo após o comando, simule uma queda de energia, reiniciando o micro. Nos testes que fiz, o novo registro foi perdido.

Repetindo o mesmo teste, mas usando o AdsWriteAllRecords() ao invés do DbCommitAll(), o lançamento fica registrado.

Hard commit ou algo assim

Enviado: 29 Ago 2014 19:14
por Jairo Maia
Olá vilian,

Também fiquei surpreso com sua afirmação, e fiz os testes aqui, primeiro abrindo em rede, e na estação, deixei o browse aberto. Meu sistema faz um refresh a cada 10 segundos para exibir no browse os novos registros inseridos, e aparecem normalmente no browse, o que significa que foram salvos. Depois, no servidor coloquei um Quit após o DbCommitAll(), inseri um registro, obviamente o servidor abortou, e o registro apareceu normalmente na estação. Ao reiniciar o sistema no servidor, os registros haviam sido salvos.

Então fui verificar o fonte da função DbCommitAll(), que é:

Código: Selecionar todos

HB_FUNC( DBCOMMITALL )
{
   hb_rddFlushAll();
}
E da função hb_rddFlushAll() é (veja os comentarios):

Código: Selecionar todos

HB_EXPORT void hb_rddFlushAll( void )
{
   USHORT uiArea = hb_rddGetCurrentWorkAreaNumber(), uiIndex;    // Pega area atual

   for( uiIndex = 1; uiIndex < s_uiWaMax; ++uiIndex )            // inicia o laço para cada area aberta
   {
      hb_rddSelectWorkAreaNumber( s_WaList[ uiIndex ]->uiArea ); // seleciona uma a uma area aberta
      SELF_FLUSH( s_pCurrArea );                                 // salva os registros da area selecionada
   }
   hb_rddSelectWorkAreaNumber( uiArea );                         // volta a area que estava aberta
}
A Função hb_rddFlushAll() poderia simplesmente também ser escrita assim:

Código: Selecionar todos

Function SalvaTudo()
 Local cAlias := Alias(), nArea := 1
 While Select( nArea )
  If Used()
   DbCommit()
   nArea++
  Else
   Exit
  EndIf
 EndDo
 Select( cAlias )
Return Nil
Assim, não vejo motivo para não acreditar nessa função.

Hard commit ou algo assim

Enviado: 29 Ago 2014 19:22
por ANDRIL
Jairo Maia escreveu:no servidor coloquei um Quit após o DbCommitAll()
Acho que o QUIT encerra todas as áreas abertas e encerra o que tem que ser encerrado, o que difere de uma queda de energia. Em se tratando de CACHE de DISCO tem que verificar como o Windows também esta tratando isso, já vi casos de gravar um registro e após uma reinicialização não estar mais devido ao bendito CACHE.

Vamos acompanhar...

Hard commit ou algo assim

Enviado: 29 Ago 2014 19:51
por Jairo Maia
Olá Pessoal,

Com base no que o Andril disse:
ANDRIL escreveu:Acho que o QUIT encerra todas as áreas abertas e encerra o que tem que ser encerrado
Fiz um novo teste trocando o Quit por Alert("ok"), e quando o alert apareceu, desconectei o cabo de energia do servidor (para simular uma queda real de energia). Na estação o registro apareceu (claro, após reiniciar o sistema), bem como no servidor. Porém, acho (destaco: acho) que isso pode ter algo a ver:
ANDRIL escreveu:Em se tratando de CACHE de DISCO tem que verificar como o Windows também esta tratando isso
Assim, como o Andril disse: Vamos acompanhar...

[Errata:]Onde se le na minha postagem anterior:
While Select( nArea ), leia: While Select( nArea ) != 0

Hard commit ou algo assim

Enviado: 29 Ago 2014 20:27
por ANDRIL
Jairo, disse sobre o CACHE DE DISCO por que este problema de sumiço ocorre uma hora ou outra e geralmente com esta ativado este serviço no Windows. É uma possibilidade a ser testada.

Vamos ver!