31 Ago 2010 01:33
SELE CLIENTES
...
lSemaforo := .f.
if CLIENTES->IDESTACAO = 0
// SEMAFORO LIGADO
CLIENTES->( dbRLock() )
CLIENTES->IDESTACAO := user_id // Travo o registro, salvo o IDentificador do usuario e libero o registro
CLIENTES->( dbUnlock() )
CLIENTES->( dbCommit() )
else
lSemaforo := .t.
//Isto eu nao quero
//MsgRun( "Registro "+alltrim(str(CLIENTES->IDCLIENTE))+" sendo atualizacao em outra estacao!" )
//return .t.
endif
...
// Carregos os campos em variaveis e faço a alteração ou visualizao
...
ACTIVATE DIALOG oDialog ON INIT iif( lSemaforo, oButton:Disable(), oButton:Enable() )
...
...
REDEFINE BUTTON oButton ID 100 OF oDialog PROMPT "Confirma e fecha." ACTION ( lSave := .t. , oDialog:End() )
...
ACTIVATE DIALOG oDialog ON INIT iif( lSemaforo, oButton:Disable(), oButton:Enable() )
if lSave
// Salvar o Registro
...
else
GO nRegClient
if CLIENTES->IDESTACAO # 0 // Se o registro foi marcado
if CLIENTES->IDESTACAO = user_id // Se o usuario e o mesmo que marcou
// MsgRun( "Liberando o registro" )
// SEMAFORO LIGADO
CLIENTES->( dbRLock() )
CLIENTES->IDESTACAO := 0
CLIENTES->( dbUnlock() )
CLIENTES->( dbCommit() )
endif
endif
endif
26 Mar 2011 04:57
rochinha escreveu:Ao implementar o procedimento de semaforos em nossos sistemas nos deparamos sempre com o seguinte problema:
Se um registro for travado em uma estação, outra estação não poderá ter acesso a alteração do mesmo. Então implementamos a seguinte mensagem. registro travado em outra estação.
Poxa, mas se ta travado não posso fazer nada?
Posso sim, Visualiza-lo.
Mas como visualizar sem causar algum tipo de problema no mesmo.
Como sabemos a função RLock() ou dbRlock() é uma faca de dois legumes. Se numa rede duas maquinas tentam ao mesmo tempo travar um registro no final o que teremos é um registro destravado, pois num milésimo de segundo o registro foi travado e no outro destravado.
Então a solução, sempre será o uso de semáforos e cada um implementa da forma mais coerente e funcional.
Estes problemas de travamento não é só dos RDDs NTX/CDX e acontecem também no MySQL( já tive relatos de dificuldades neste sentido ).
No meu caso, a idéia não seria apresentar uma mensagem ao usuário e fechar, mas sim permitir ao usuário ainda visualizar o registro sem permitir alterações.
Todas as minhas tabelas possuem um campo identificador unico que chamo de IDESTACAO mas voce pode criar o seu a seu gosto.
26 Mar 2011 11:11
26 Mar 2011 11:39
Comigo nunca aconteceu isso ou ao menos nunca poderia ter acontecido, pois a idéia de travar registro pelo RLOCK() é necessária em rede mas o tratamento através de uso de semáforos aliada com todo o tratamento de rede (RLOCK, FLOCK, UNLOCK...) são bem vindos. Acho mais provável falhar o semáforos que não sejam bem implementados do que o uso do RLOCK. Bem essa é a minha opinião.O que não tem sentido seria usar um rlock() para travar um registro, tendo em vista que o mesmo é falho, ou nunca aconteceu com voce, de travar um registro em um terminal e outro terminal ao travar o mesmo registro destravar o primeiro.
26 Mar 2011 11:52
26 Mar 2011 17:08
rochinha escreveu:Costumo trabalhar em rede usando variáveis para suporte aos dados dos campos que pretendo alterar ou não.
No final se eu realmente desejo salvar o conteudo, executo o travamento do registro e pronto.
Este é o método praxe para manutenção de dados em rede.
...
Não usei aqui técnicas de semáforo para registro através de travamentos por rlock() e sim uma alternativa menos falível que a primeira.
Com certeza voce não entendeu a proposta da rotina e não leu os comentários.
O programador que se utilizar da rotina encontrará meios de melhorá-la ou pelo menos terá uma idéia de como usar a própria interface para auxiliá-lo.
A técnica do semáforo tem mais longevidade que meus poucos 25 anos de programação e raras vezes fiz uso da mesma.
Quanto a queda de energia, ai já é outra rotina...
Fique a vontade a melhorar a idéia.
rochinha escreveu:O que não tem sentido seria usar um rlock() para travar um registro, tendo em vista que o mesmo é falho, ou nunca aconteceu com voce, de travar um registro em um terminal e outro terminal ao travar o mesmo registro destravar o primeiro.
26 Mar 2011 17:21
Rochinha,
En Clipper on line usted explica como usar semaforos.
Yo hace tiempo lo resolvi de otra forma y se lo comento por si le interesa.
Dado un documento o un cliente con el nº 000001, yo creo un archivo .txt que se llame:
Blq_Cliente_000001.txt y lo abro en modo shared.
Blq_cliente_000001.txt contiene la informacion del usuario que tiene el documento.
Lo que me di cuenta es que habia que sacar del tema de semaforos la logica de bloqueos rlock(), (nunca probe el multibloqueo) porque el mismo usuario que hace un rlock, puede querer hacer un unlock en otra derivacion del mismo programa:
Ademas con este sistema no es necesario ningun campo de id de la .dbf, ni tampoco identificar las estaciones de trabajo)
Voceto: Hay que añadir un array statico con los cid y los nHandle para cerrar:
FUNCTION Semaforo(cFile, cId, lSemaforo)
Local cFile:= cPath+ "Blq_"+ cFile+ "_"+ cId
IF lSemaforo
IF !File(cFile) .OR. lUsado(cFile)
ELSE
ENDIF
ELSE
DELETE FILE (cFile)
ENDIF
RETURN NIL
Saludos
26 Mar 2011 17:29
26 Mar 2011 18:54
rochinha escreveu:Se um dia sentarmos para discutir programação, que seja numa mesa de bar, bebendo e gargalhando.