Página 2 de 4

ok...pessoal.

Enviado: 20 Mai 2007 08:40
por scom
obrigado a todos pela ajuda.


vou verificar essas opções.

ROBSON

Enviado: 20 Mai 2007 10:47
por Augusto
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:

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

Enviado: 20 Mai 2007 12:31
por sygecom
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

Enviado: 20 Mai 2007 17:27
por Maligno
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

Enviado: 20 Mai 2007 17:39
por Maligno
MARCELOG escreveu:A sua rotina está tentando bloquear um registro qye já está bloqueado, por isso tá falhando.
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.

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 
Se num sistema que usa uma lógica pessimista, onde existe em algum lugar a possibilidade de bloqueio do arquivo, para atendar alguma função específica, a chamada a NetErr() é necessária (o append poderia falhar). Mas se for usada uma lógica otimista (sem bloqueio de arquivo), NetErr() poderá ser descartada (o append nunca falhará).

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

Enviado: 20 Mai 2007 20:51
por Eolo
Complementando:

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 
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.

Enviado: 20 Mai 2007 23:22
por Maligno
Eolo escreveu:Ainda, só pra deixar mais claro: o FLOCK() não "bloqueia totalmente" o arquivo na rede.
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.
Obrigado pelo complemento, Eolo.

[]'s
Maligno
http://www.buzinello.com/prg

Enviado: 21 Mai 2007 08:41
por Eolo
Maligno,

Putz, e eu nem tinha reparado tb! Por isso, fiz 2 observações: a primeira, me referindo a vc, sobre a falta do DBCOMMIT(); a outra, foi geral, porque vi todo mundo falando de " bloqueio do arquivo" e achei que merecia o esclarecimento.

Enviado: 21 Mai 2007 08:56
por Maligno
Eolo escreveu:Putz, e eu nem tinha reparado tb!
Estamos ficando velhos. :)))))

[]'s
Maligno
http://www.buzinello.com/prg

Enviado: 21 Mai 2007 09:36
por Pablo César
Analisando um pouco...
scom escreveu:IF CONF='S'
APPEND BLANK
IF REG_LOCK() // FUNÇÃO PARA TRAVAR O REGISTRO
Aqui há dois detalhes relevantes em rede:

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
ENDIF
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:
Editado pela última vez por Maligno em 20 Maio 2007 23:23; num total de 1 vez
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:
Poxa! Agora que vi. Eu estava me referindo ao FLock() quando na verdade eu deveria me referir ao RLock().
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.

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 !
Imagem

Um clip-abraço :)Pos

Enviado: 21 Mai 2007 09:48
por MARCELOG
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

Enviado: 21 Mai 2007 10:00
por Pablo César
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:

Código: Selecionar todos

SELE 1
USE CLIENTES SHARED
APPEND BLANK
? RLOCK()
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...

Enviado: 21 Mai 2007 10:20
por Maligno
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
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. :)))

[]'s
Maligno
http://www.buzinello.com/prg

Enviado: 21 Mai 2007 10:31
por Maligno
MARCELOG escreveu:E o rlock() falhará se o registro já estiver bloqueado, retornando .F. (veja documentação).
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.
Por isso ele está tendo registros em branco no arquivo.
Ainda acho que o problema dos registro em branco tem origem em outra situação.
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.
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.
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.

[]'s
Maligno
http://www.buzinello.com/prg

Enviado: 21 Mai 2007 10:36
por Eolo
Mas a utilização do FLOCK() para inclusão de registros... não o vejo com bons olhos... em rede ?... ummmm
Pablo,

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.