problema de registros em branco no dbf.
Moderador: Moderadores
ok...pessoal.
obrigado a todos pela ajuda.
vou verificar essas opções.
ROBSON
vou verificar essas opções.
ROBSON
S COM INFORMÁTICA
CLIPPER 5.3 / FIVEWIN 2.0 / BLINKER 7
XHARBOUR/ BCC582
CLIPPER 5.3 / FIVEWIN 2.0 / BLINKER 7
XHARBOUR/ BCC582
- Augusto
- Usuário Nível 3

- Mensagens: 473
- Registrado em: 26 Ago 2003 17:50
- Localização: Maricá/RJ
- Contato:
Marcelo,
Desculpe contestar, mais a sua rotina comete o mesmo erro de lógica que a do parceiro SCOM...
A questão é a criação do registro (APPEND BLANK) e a possível não utilização do mesmo caso a condição do "IF" (seja a que vc sugere ou a dele) não seja satisfeita. Preste atenção que o ERRO reside exatamente nesse momento.
Volto a dizer que o travamento deve ser feito no ARQUIVO (flock) e não no registro (rlock) assim como o APPEND deverá ser dado somente se a condição for verdadeira, portanto, dentro do IF e não por fora como vc e o SCOM demonstraram pois, desta forma o registro continuará sendo criado em branco independentemente do "teste" feito para verificar a utilização do "arquivo" por outro usuário...
Entenda o que digo:
Desculpe contestar, mais a sua rotina comete o mesmo erro de lógica que a do parceiro SCOM...
A questão é a criação do registro (APPEND BLANK) e a possível não utilização do mesmo caso a condição do "IF" (seja a que vc sugere ou a dele) não seja satisfeita. Preste atenção que o ERRO reside exatamente nesse momento.
Volto a dizer que o travamento deve ser feito no ARQUIVO (flock) e não no registro (rlock) assim como o APPEND deverá ser dado somente se a condição for verdadeira, portanto, dentro do IF e não por fora como vc e o SCOM demonstraram pois, desta forma o registro continuará sendo criado em branco independentemente do "teste" feito para verificar a utilização do "arquivo" por outro usuário...
Entenda o que digo:
Código: Selecionar todos
DO WHILE .T.
DESC = SPACE(45)
MARC = SPACE(10)
APLI = SPACE(100)
@ 02,03 say 'Descrição:' GET DESC
@ 03,03 say 'Marca: ' GET MARC
@ 04,03 say 'Aplicação:' GET APLI
READ
IF LASTKEY()=27
EXIT
ENDIF
CONFSN()
IF CONF='S'
DO WHILE FLOCK() //Ou qqr função que substitua
LOOP
ENDDO
FLOCK()
APPEND BLANK
REPLACE A_DESC WITH DESC, A_MARC WITH MARC, A_APLI WITH APLI
COMMIT
UNLOCK
ELSE
LOOP
ENDIF
ENDDO:xau Fui...
goulart@provsul.com.br
Faça da PROVSUL o seu Provedor de Serviços WEB
Visite: www.PROVSUL.com.br
goulart@provsul.com.br
Faça da PROVSUL o seu Provedor de Serviços WEB
Visite: www.PROVSUL.com.br
- sygecom
- Administrador

- Mensagens: 7131
- Registrado em: 21 Jul 2006 10:12
- Localização: Alvorada-RS
- Contato:
Augusto, é verdade o que vc falou..pelo o que vi vai mais ou menos fazer a mesma coisa.....mas tb. no seu acho que não ha nescessidade de bloquear o arquivo todo.....a propria APPEND BLANK jah cria um novo registro bloqueado...ele soh tem que liberar depois dos REPLACE...ou seja mesmo que ele esteja abrindo os arquivos em SHARED e esteja em rede esse sistema....nunca vai abrir um novo registro na mesma area...
Abraços
Leonardo Machado
Abraços
Leonardo Machado
Leonardo Machado
xHarbour.org + Hwgui + PostgreSql
xHarbour.org + Hwgui + PostgreSql
Augusto escreveu:Volto a dizer que o travamento deve ser feito no ARQUIVO
Este pensamento não está errado. Entretanto, não é o mais aconselhável e nem é necessário. Num arquivo pequeno, com pouco tráfego, tudo bem. Mas imagine quando há muitos usuários concorrendo para acessá-lo. Bloquear o arquivo todo só vai dificultar o trabalho.
[]'s
Maligno
http://www.buzinello.com/prg
Mas bloquear um registro já bloqueado não representa falha quando o bloqueio inicial foi feito pela mesma instância. Faça o teste. Abra um banco, execute um append e bloqueie o mesmo registro novamente (e outras tantas vezes, se quiser). Você vai reparar que seus RLock() retornarão sempre TRUE. E nem poderia ser diferente. A instância é a mesma. Um bloqueio extra não sobreporá o antigo, mas será ignorado pelo sistema operacional.MARCELOG escreveu:A sua rotina está tentando bloquear um registro qye já está bloqueado, por isso tá falhando.
O problema de registros em branco está em outro lugar. O código do Robson (OP) não tem erro algum. Apenas uma pequena falha: executar uma RLock() desnecessária. E, claro, não desbloquear o registro após o replace.
Apesar do código dele não ter nenhum erro grave, acho que ficaria melhor assim:
Código: Selecionar todos
CONFSN()
IF CONF='S'
APPEND BLANK
IF !NetErr()
REPLACE A_DESC WITH DESC,;
A_MARC WITH MARC,;
A_APLI WITH APLI
dbUnLock()
ENDIF
ENDIF
Repetindo: o problema do colega está em outro lugar do código. Muito embora eu não descarte um problema de corrupção de estrutura. Já vi isso acontecer com um DBF corrompido. O arquivo funcionava pra tudo, mas dava exatamente o mesmo tipo de erro de vez em quando. A solução foi exportar os dados para um DBF "limpo" recém-criado.
[]'s
Maligno
http://www.buzinello.com/prg
Editado pela última vez por Maligno em 20 Mai 2007 23:23, em um total de 1 vez.
Complementando:
Faltou um DBCOMMIT() no exemplo do Maligno. Sem ele, o registro APPENDado pode não ficar visível de imediato na rede...
Ainda, só pra deixar mais claro: o FLOCK() não "bloqueia totalmente" o arquivo na rede.
a) com o USE SHARED e depois FLOCK(), o arquivo continua acessível a todos na rede, mas só para leitura. Só tem acesso para gravação (alterações) a instância que conseguiu o FLOCK().
b) já com o USE EXCLUSIVE, o acesso é exclusivo de quem comandou. Ninguém mais consegue ter acesso ao arquivo, nem pra leitura.
Faltou um DBCOMMIT() no exemplo do Maligno. Sem ele, o registro APPENDado pode não ficar visível de imediato na rede...
Código: Selecionar todos
CONFSN()
IF CONF='S'
APPEND BLANK
IF !NetErr()
REPLACE A_DESC WITH DESC,;
A_MARC WITH MARC,;
A_APLI WITH APLI
dbcommit() // <------------------
dbUnLock()
ENDIF
ENDIF
a) com o USE SHARED e depois FLOCK(), o arquivo continua acessível a todos na rede, mas só para leitura. Só tem acesso para gravação (alterações) a instância que conseguiu o FLOCK().
b) já com o USE EXCLUSIVE, o acesso é exclusivo de quem comandou. Ninguém mais consegue ter acesso ao arquivo, nem pra leitura.
Poxa! Agora que vi. Eu estava me referindo ao FLock() quando na verdade eu deveria me referir ao RLock(). Eu nunca travo registro desse jeito e acabei me distraindo. E eu nunca travo arquivo nem nunca uso o modo exclusivo.Eolo escreveu:Ainda, só pra deixar mais claro: o FLOCK() não "bloqueia totalmente" o arquivo na rede.
Obrigado pelo complemento, Eolo.
[]'s
Maligno
http://www.buzinello.com/prg
Estamos ficando velhos.Eolo escreveu:Putz, e eu nem tinha reparado tb!
[]'s
Maligno
http://www.buzinello.com/prg
- Pablo César
- Usuário Nível 7

- Mensagens: 5312
- Registrado em: 31 Mai 2006 10:22
- Localização: Curitiba - Paraná
Analisando um pouco...
1. Quando é executado o APPEND BLANK, deverá ser precedido com o NETERR() para verificar se o adicionamento de registro em branco foi feito com sucesso. Pois o arquivo DBF em questão, poderia estar bloqueado, ora seja por outro terminal ou por este em outra instância. Ora seja por terem utilizado o FLOCK() ou o uso EXCLUSIVE do DBF. Mas é necessário a utilização do NETERR() para ter certeza que o adicionamento de registro em branco foi realizada com sucesso.
2. A utilização de REG_LOCK() do colega SCOM, que bloqueia registro, é totalmente desnecessária, pois o APPEND BLANK bloqueia automáticamente o novo registro, e é desbloqueado somente apenas quando é utilizado o comando UNLOCK ou até mesmo fazendo outro RLOCK() na mesma area. Portanto a utilização do FLOCK() após ou antes do APPEND BLANK, estaria redundante e a sua utilização poderia estar provocando o erro, isto é, estaria sendo testado duas vezes o bloqueio, e seria este uma das causas que FAZ o APPEND e não faz o bloqueio do registro (provocando os registros em branco). Sei Maligno que você defende a tese que se utiliza o RLOCK() ele volta .T. (porque é a mesma instância) mesmo após de um APPEND BLANK... (concordo, com a sua tese) mas na prática eu tenho minhas dúvidas (por lei de Murphy).
Não sei se os colegas alguma vez passaram por esta situação, mas comigo ja aconteceu que mesmo que todos os terminais estarem fora do aplicativo, os sistema dizer para apenas UM terminal, que aquele arquivo estava aberto e que não poderia ser aberto nesse momento. Nesse acontecimento, verifiquei se tinha alguma janela minimizada e verifiquei TODAS as estações. O jeito foi desligar o servidor... pode ?. Por isso, guardo as minhas ressalvas... Não acredito 100% de seguridade nos DBFs, assim como a outra questão que foi levantada pelo Maligno, também acho muito passível de acontecer, isso de ter que RECRIAR o arquivo DBF, principalmente se o BD foi feito com outro aplicativo que não tenha sido em Clipper puro.
Um bom exemplo foi do Marcelog:
A utilização do EXCLUSIVE, muito casualmente é utilizado, porém desaconselhado em rede. Também o modo READONLY, também ajudaria nos casos indicados para elaboração de relatórios no qual não haja necessidade de gravação no DBF, é claro.
Por isso, é muito conveniente utilizar-se de funções de tratamento em rede, assim como: ABREARQ(), ADIREG(), BLOQREG(), BLOQARQ().
Mas a utilização do FLOCK() para inclusão de registros... não o vejo com bons olhos... em rede ?... ummmm (e não me refiro tão somente ao comentário do Maligno, que ora tenha reconhecido de ter trocado na menção de FLOCK() para RLOCK(), digo isto porque foi mencionado anteriormente).
No entanto Maligno, quando você percebeu seu erro você RE-EDITOU sua mensagem. Sei isto porque no rodapé da sua mensagem, o sistema do FORUM menciona:
Obs.: Por falar em Maligno, onte a noite na A&E Mundo, passaram o filme "AUSTIN POWERS" onde o Dr. Evil ("o Maligno"), conhecido também como Dr. Perverso.... hehe não dá para não lembrar de você Paulo.... hehehe mas este se deu mal... ficou na órbita do espaço (congelando-se junto ao seu gato)... é um barato !

Um clip-abraço :)Pos
Aqui há dois detalhes relevantes em rede:scom escreveu:IF CONF='S'
APPEND BLANK
IF REG_LOCK() // FUNÇÃO PARA TRAVAR O REGISTRO
1. Quando é executado o APPEND BLANK, deverá ser precedido com o NETERR() para verificar se o adicionamento de registro em branco foi feito com sucesso. Pois o arquivo DBF em questão, poderia estar bloqueado, ora seja por outro terminal ou por este em outra instância. Ora seja por terem utilizado o FLOCK() ou o uso EXCLUSIVE do DBF. Mas é necessário a utilização do NETERR() para ter certeza que o adicionamento de registro em branco foi realizada com sucesso.
2. A utilização de REG_LOCK() do colega SCOM, que bloqueia registro, é totalmente desnecessária, pois o APPEND BLANK bloqueia automáticamente o novo registro, e é desbloqueado somente apenas quando é utilizado o comando UNLOCK ou até mesmo fazendo outro RLOCK() na mesma area. Portanto a utilização do FLOCK() após ou antes do APPEND BLANK, estaria redundante e a sua utilização poderia estar provocando o erro, isto é, estaria sendo testado duas vezes o bloqueio, e seria este uma das causas que FAZ o APPEND e não faz o bloqueio do registro (provocando os registros em branco). Sei Maligno que você defende a tese que se utiliza o RLOCK() ele volta .T. (porque é a mesma instância) mesmo após de um APPEND BLANK... (concordo, com a sua tese) mas na prática eu tenho minhas dúvidas (por lei de Murphy).
Não sei se os colegas alguma vez passaram por esta situação, mas comigo ja aconteceu que mesmo que todos os terminais estarem fora do aplicativo, os sistema dizer para apenas UM terminal, que aquele arquivo estava aberto e que não poderia ser aberto nesse momento. Nesse acontecimento, verifiquei se tinha alguma janela minimizada e verifiquei TODAS as estações. O jeito foi desligar o servidor... pode ?. Por isso, guardo as minhas ressalvas... Não acredito 100% de seguridade nos DBFs, assim como a outra questão que foi levantada pelo Maligno, também acho muito passível de acontecer, isso de ter que RECRIAR o arquivo DBF, principalmente se o BD foi feito com outro aplicativo que não tenha sido em Clipper puro.
Um bom exemplo foi do Marcelog:
Código: Selecionar todos
IF LASTKEY()<>27
IF PERGUNTA("Confirma inclusão ?")="S"
SELE 1 // Eu utilizaria isto para garantir que está na área correta
APPEND BLANK
IF !NetErr()
REPLACE A_DESC WITH DESC
REPLACE A_MARC WITH MARC
REPLACE A_APLI WITH APLI
DBCommit() // E o uso do COMMIT indicado pelo Eolo, é bom
Unlock
ENDIF
ENDIF
ENDIFPor isso, é muito conveniente utilizar-se de funções de tratamento em rede, assim como: ABREARQ(), ADIREG(), BLOQREG(), BLOQARQ().
Mas a utilização do FLOCK() para inclusão de registros... não o vejo com bons olhos... em rede ?... ummmm (e não me refiro tão somente ao comentário do Maligno, que ora tenha reconhecido de ter trocado na menção de FLOCK() para RLOCK(), digo isto porque foi mencionado anteriormente).
No entanto Maligno, quando você percebeu seu erro você RE-EDITOU sua mensagem. Sei isto porque no rodapé da sua mensagem, o sistema do FORUM menciona:
Mas seria bom Maligno, que você faça uma ressalva abaixo (digamos colocando um asterisco) em cada RLOCK() que você REDITOU. Pois daqui algum tempo, fica meio confusso o entendimento no seu conteúdo total, ora porque você adicionou uma nova mensagem dizendo:Editado pela última vez por Maligno em 20 Maio 2007 23:23; num total de 1 vez
Evidentemente que após a sua RE-EDIÇÃO todos os FLOCK() SUMIRAM (embora do Eolo, ainda não)... hehe Ou então APAGAR essa sua ultimas mensagens que você acusa o erro cometido...(e deixar as mensagens como se não tivesse ocorrido erro algum) Sei lá... só sei que eu ví tanta confusão e decidí RE-COMPILAR todas as observações dos colegas... mas agora que vejo que foi corrigida... que confusão !! hehe, isto as vezes acontece.Poxa! Agora que vi. Eu estava me referindo ao FLock() quando na verdade eu deveria me referir ao RLock().
Obs.: Por falar em Maligno, onte a noite na A&E Mundo, passaram o filme "AUSTIN POWERS" onde o Dr. Evil ("o Maligno"), conhecido também como Dr. Perverso.... hehe não dá para não lembrar de você Paulo.... hehehe mas este se deu mal... ficou na órbita do espaço (congelando-se junto ao seu gato)... é um barato !

Um clip-abraço :)Pos
Editado pela última vez por Pablo César em 21 Mai 2007 09:49, em um total de 1 vez.
-
MARCELOG
- Usuário Nível 4

- Mensagens: 546
- Registrado em: 15 Mar 2005 16:54
- Localização: Divinópolis/MG
Caro Maligno,
"Cê tá ficando veio" veio (bricadeirinha!!).
No caso do nosso amigo, ela está fazendo a indagação quanto ao bloqueio do registro para aplicar o replace dos campos.
E o rlock() falhará se o registro já estiver bloqueado, retornando .F. (veja documentação).
Assim, a função que "trava registro" do nosso amigo será negativa porque o registro já foi bloqueado (travado) quando utilizou-se o append blank.
Logo, tudo dentro do "if" será ignorado.
Por isso ele está tendo registros em branco no arquivo.
O append blank cria o registro em branco e trava, mas os "replace"s, por conta da impossibilidade de travamento do registro (que já está bloqueado/ travado) não acontece.
Assim, ele "commita" ou destrava certinho, mas um registro em branco.
Tudo dentro do "if" foi ignorado porque a condição (que deveria ser verdadeira) não foi satisfeita!
MarceloG
"Cê tá ficando veio" veio (bricadeirinha!!).
No caso do nosso amigo, ela está fazendo a indagação quanto ao bloqueio do registro para aplicar o replace dos campos.
E o rlock() falhará se o registro já estiver bloqueado, retornando .F. (veja documentação).
Assim, a função que "trava registro" do nosso amigo será negativa porque o registro já foi bloqueado (travado) quando utilizou-se o append blank.
Logo, tudo dentro do "if" será ignorado.
Por isso ele está tendo registros em branco no arquivo.
O append blank cria o registro em branco e trava, mas os "replace"s, por conta da impossibilidade de travamento do registro (que já está bloqueado/ travado) não acontece.
Assim, ele "commita" ou destrava certinho, mas um registro em branco.
Tudo dentro do "if" foi ignorado porque a condição (que deveria ser verdadeira) não foi satisfeita!
MarceloG
- Pablo César
- Usuário Nível 7

- Mensagens: 5312
- Registrado em: 31 Mai 2006 10:22
- Localização: Curitiba - Paraná
Desculpa Marcelo, que me intrometa no seu ultimo questionamento com o Maligno. Mas veja que a tentativa de usar o RLOCK não causa erro (normalmente). Se você fizer um teste:
Você verá que o RLOCK() retornou .T. No entanto, como eu me expliquei, tenho as minhas ressalvas, ora porque você testa uma vez, duas, tres e a principio dará sempre .T. Mas eu não confio de todas formas. As vezes essas questões (tenho a minha impressão) que como você... poderia eventualmente dar alguma interpretação equívoca. Mas eu não posso afirmar isso. Por vias das dúvidas, eu não o faço.
Um clip-abraço :)Pos
Obs.: Contraritório eu, né ?.... se digo que sempre, deveria ser sempre. Mas ao que vou dizendo com isto, que para quê deve ser feito o pedido de bloqueio de registro, se o APPEND BLANK ja faz isso...
Código: Selecionar todos
SELE 1
USE CLIENTES SHARED
APPEND BLANK
? RLOCK()Um clip-abraço :)Pos
Obs.: Contraritório eu, né ?.... se digo que sempre, deveria ser sempre. Mas ao que vou dizendo com isto, que para quê deve ser feito o pedido de bloqueio de registro, se o APPEND BLANK ja faz isso...
Se alguém ler atenciosamente a seqüência de mensagens e ainda assim não perceber que houve um engano da minha parte (com a necessária correção), sinto muito. Vai ficar sem entender. E não tenho dó nenhuma.Pablo César escreveu:Mas seria bom Maligno, que você faça uma ressalva abaixo (digamos colocando um asterisco) em cada RLOCK() que você REDITOU. Pois daqui algum tempo, fica meio confusso o entendimento no seu conteúdo total, ora porque você adicionou uma nova mensagem
[]'s
Maligno
http://www.buzinello.com/prg
Um RLock() extra não retornará FALSE se o registro já estiver travado pela mesma instância em que ele é utilizado. Faça o teste.MARCELOG escreveu:E o rlock() falhará se o registro já estiver bloqueado, retornando .F. (veja documentação).
Ainda acho que o problema dos registro em branco tem origem em outra situação.Por isso ele está tendo registros em branco no arquivo.
Se essa fal função REG_LOCK() que ele usa tiver um bug qualquer, é lógico que isso poderá ser o motivo dos registros em branco. Agora, se no lugar dessa REG_LOCK() ele usar um simples RLock() os replaces ocorrerão normalmente. Aliás, note que ele não postou o código dessa função REG_LOCK(). Portanto, não podemos avaliar se nela existe algum bug que a faça retornar FALSE.
Como eu disse: faça o teste. Crie um programa que abre um arquivo qualquer. Faça um append blank e em seguida execute RLock() 20 vezes. Nas 20 vezes RLock() retornará TRUE.O append blank cria o registro em branco e trava, mas os "replace"s, por conta da impossibilidade de travamento do registro (que já está bloqueado/ travado) não acontece.
[]'s
Maligno
http://www.buzinello.com/prg
Pablo,Mas a utilização do FLOCK() para inclusão de registros... não o vejo com bons olhos... em rede ?... ummmm
Imagine a seguinte situação: eu tenho o arquivo CLIENTES.dbf, indexado por nome, que NÃO PODE ter nomes duplicados e que PODE ser atualizado por todas as estações da rede. Em outras palavras: todas as estações abrem o arquivo SHARED e todas as estações podem APPENDar registros nele.
Então, é possível que, num mesmo exato momento, duas estações façam, simultâneamente, o seguinte:
- procurem e não achem o registro "Eolo";
- APPENDem um novo registro cada uma;
- façam o REPLACE com "Eolo",
caso em que o DBF vai acabar contendo dois registros "Eolo"...
Como vc faz, num caso destes, para evitar a duplicidade de nomes?
Eu entendo que o FLOCK() foi criado exatamente pra isso: ele continua dando acesso a todos na rede (para leitura) mas limita o "write" a só uma estação, que vai assim APPENDar o "Eolo" sem risco de duplicidade. Entendo, ainda, que o FLOCK() só não é necessário quando vc vai alterar um campo que não é chave. Aí o APPEND BLANK (com o "rlock" automático) ou o RLOCK() simultâneos (de várias estações) dão conta do recado.

