Página 1 de 1

Erro em abertura de rede

Enviado: 17 Ago 2010 17:03
por Josmar dos Santos
Boa tarde, Por que ocorre esse erro quando compartilho o mesmo arquivo (CLIENTES.DBF) em dois ou mais terminais diferentes ???

Código: Selecionar todos

Error DBFCDX/1022 Lock required
Sem mais obrigado,
Josmar

:))

Re: Erro em abertura de rede

Enviado: 17 Ago 2010 17:20
por Pablo César
mostre como você está abrindo o arquivo clientes

Re: Erro em abertura de rede

Enviado: 17 Ago 2010 17:34
por Josmar dos Santos
Pablo, eis a rotina:

Código: Selecionar todos

*-> Abro o arquivo cliente através dessa rotina
IF !ABRECLI()
   ALERT("NAO CONSEGUI ABRIR")
ENDIF

*-> Essas são as funções de rede que estou utilizando
FUNCTION ABRECLI
IF USA("CLIENTES",.T.,.F.)
   IF(!FILE("CLIENTE.CDX"))
     _FECHA()
     INDEX ON COD_CLI TAG CLIENT_1 TO CLIENTE
     INDEX ON NOM_CLI TAG CLIENT_2 TO CLIENTE
     _ABRE()
   ENDIF
   DBSETINDEX("CLIENTE")
ELSE
   MENSAGEM( "Troca de n¡vel mal sucedida", 3 )
   RETURN .F.
ENDIF
RETURN .T.

FUNCTION USA(ARQUIVO,SH,RO)
IF SH
   USE &ARQUIVO SHARED NEW
ELSE
   USE &ARQUIVO EXCLUSIVE NEW
ENDIF
IF !NETERR()
   memory(0)
   RETURN .T.
ELSE
   RETURN .F.
ENDIF

FUNCTION _FECHA
LOCAL WDBF
WDBF = ALIAS()
CLOSE &WDBF
USA(WDBF,.F.,.F.)
RETURN

FUNCTION _ABRE
LOCAL WDBF
WDBF = ALIAS()
CLOSE &WDBF
USA(WDBF,.T.,.F.)
RETURN
:xau

Re: Erro em abertura de rede

Enviado: 17 Ago 2010 17:44
por alxsts
Olá!

O erro em questão não é no momento da abertura do arquivo e sim no momento em que algo está sendo gravado nele (ex: Replace ou CLIENTES->razaosocial := cRazaoSocial). É preciso travar o registro antes da gravação.

Código: Selecionar todos

CLIENTES->( RLock(), CLIENTES->razaosocial := crazaosocial, DbCommit(), DbUnLock() )

Re: Erro em abertura de rede

Enviado: 17 Ago 2010 17:57
por Josmar dos Santos
Ola Alxsts, sim de fato vc está correto ! é exatamente isso q ocorre, mas te pergunto: como que ficaria a rotina com esse procedimento q vc passou, ou seja, onde coloca-la ??

Josmar

Re: Erro em abertura de rede

Enviado: 17 Ago 2010 19:22
por Josmar dos Santos
Entendi o que vc quis dizer, salvar dentro do arquivo, seria isso ?

Código: Selecionar todos

FUNCTION SALVAR_1
CLIENTES->(RLOCK(),CLIENTES->COD_CLI := M->COD_CLI,DBCOMMIT(),DBUNLOCK())
CLIENTES->(RLOCK(),CLIENTES->NOM_CLI := M->NOM_CLI,DBCOMMIT(),DBUNLOCK())
CLIENTES->(RLOCK(),CLIENTES->DAT_CLI := M->DAT_CLI,DBCOMMIT(),DBUNLOCK())
CLIENTES->(RLOCK(),CLIENTES->V_CLI := M->V_CLI,DBCOMMIT(),DBUNLOCK())
CLIENTES->(RLOCK(),CLIENTES->OBS_CLI := M->OBS_CLI,DBCOMMIT(),DBUNLOCK())
.

Se for blz, ainda não testei na rede, amanhã, irei testa-la !

Re: Erro em abertura de rede

Enviado: 18 Ago 2010 00:38
por alxsts
Olá!

Caro Josmar:
parmita-me colocar alguns conceitos:
- quando um programa aplicativo está em execução em um ambiente de rede, além das preocupações normais, surge outra, conhecida como concorrência de acesso a dados em ambiente multiusuário. Isso acontece quando mais de um usuário da aplicação tenta acessar o mesmo registro da mesma tabela ao mesmo tempo. Isso é uma discussão bem longa, que já mereceu vários tratados...
- No bom e velho Clipper, temos que tratar isso nós mesmos, utilizando funções e comandos disponíveis na linguagem.
- basicamente, é preciso saber que se adicionamos um novo registro a uma tabela com sucesso, este registro fica disponível e já bloqueado contra o acesso de outros usuários.

Código: Selecionar todos

CLIENTES->( DbAppend() )
If .Not. NetErr()   // conseguiu inserir e deixou o registro travado...
   CLIENTES->cod := nCod
   CLIENTES->razao := cRazao
   // demais campos
   CLIENTES->( DbCommit(), DbUnLock() )
Else
   Alert( "Falha ao incluir novo cliente." )
Endif
- quando precisamos atualizar um registro em ambiente de rede, primeiro precisamos garantir que o acesso ao mesmo está assegurado apenas para nossa aplicação. Feito isso, podemos atualizá-lo:

Código: Selecionar todos

If CLIENTES->( Rlock() )  // conseguiu travar o registro...
   CLIENTES->razao := cRazao
   // demais campos
   CLIENTES->( DbCommit(), DbUnLock() )
Else
   Alert( "Falha ao alterar cliente." )
Endif
Na instalação original do Clipper 5, tem um programa que ilustra essas situações. Pode ser encontrado em :
C:\Clipper5\Source\Sample\LOCKS.PRG:

Código: Selecionar todos

/***
*
*  Locks.prg
*
*  Sample networking functions to supplant the use of USE, 
*  FLOCK(), RLOCK() and APPEND BLANK by adding additional
*  functionality
*
*  Copyright (c) 1993, Computer Associates International Inc.
*  All rights reserved.
*
*  NOTE: Compile with /a /m /n /w options
*
*/

#include "Common.ch"

#define NET_WAIT     0.5   // Seconds to wait between between retries
#define NET_SECS     2     // Number of seconds to continue retry


/***
*
*  AddRec( [<nWaitSeconds>] ) --> lSuccess
*
*  Attempt to APPEND BLANK with optional retry
*
*  Parameter:
*     nWaitSeconds - Optional time in seconds to retry operation, defaults
*                    to NET_SECS
*
*  Returns:
*     True (.T.) if successful, false (.F.) if not
*
*/
FUNCTION AddRec( nWaitSeconds )
   
   LOCAL lForever       // Retry forever?

   DEFAULT nWaitSeconds TO NET_SECS

   APPEND BLANK
   IF !NETERR()
      RETURN ( .T. )             // NOTE
   ENDIF

   lForever := ( nWaitSeconds == 0 )

   // Keep trying as long as our time's not up
   DO WHILE ( lForever .OR. ( nWaitSeconds > 0 ) )
      
      APPEND BLANK

      IF !NETERR()
         RETURN ( .T. )          // NOTE
      ENDIF

      INKEY( NET_WAIT )          // Wait NET_WAIT seconds (defined above)
      nWaitSeconds  -= NET_WAIT

   ENDDO

   RETURN ( .F. )       // Not locked



/***
*
*  FilLock( [<nWaitSeconds>] ) --> lSuccess
*
*  Attempt to FLOCK() with optional retry
*
*  Parameter:
*     nWaitSeconds - Optional time in seconds to retry operation, defaults
*                    to NET_SECS
*
*  Returns:
*     True if successful, false if not
*
*/
FUNCTION FilLock( nSeconds )
   
   LOCAL lForever    // Retry forever?

   DEFAULT nSeconds TO NET_SECS

   IF FLOCK()
      RETURN ( .T. )       // NOTE
   ENDIF

   lForever := ( nSeconds == 0 )

   // Keep trying until our time's up
   DO WHILE ( lForever .OR. ( nSeconds > 0 ) )
      
      INKEY( NET_WAIT )    // Wait NET_WAIT seconds
      nSeconds -= NET_WAIT

      IF FLOCK()
         RETURN ( .T. )    // NOTE
      ENDIF

   ENDDO

   RETURN ( .F. )          // Not locked



/***
*
*  NetUse( <cDatabase>, <lOpenMode>, [<nWaitSeconds>] ) --> lSuccess
*
*  Attempt to USE a database file with optional retry
*
*  Parameters:
*     cDatabase    - Database file to open
*     lOpenMode    - Sharing mode: True indicates EXCLUSIVE, false
*                    indicates SHARED
*     nWaitSeconds - Optional time in seconds to retry operation, defaults
*                    to NET_SECS
*
*  Returns:
*     True if successfull, false if not
*
*/
FUNCTION NetUse( cDatabase, lOpenMode, nSeconds )
   
   LOCAL lForever    // Retry forever?

   DEFAULT nSeconds TO NET_SECS
   lForever := ( nSeconds == 0 )

   // Keep trying as long as our time's not up
   DO WHILE ( lForever .OR. ( nSeconds > 0 ) )
     
     // lOpenMode determines the mode files are opened in
     IF lOpenMode       
         USE ( cDatabase ) EXCLUSIVE  
     ELSE
         USE ( cDatabase ) SHARED
     ENDIF

     IF !NETERR()
        RETURN ( .T. )     // NOTE
     ENDIF

     INKEY( NET_WAIT )     // Wait
     nSeconds -= NET_WAIT

   ENDDO

   RETURN ( .F. )          // USE fails



/***
*
*  RecLock( [<nWaitSeconds>] ) --> lSuccess
*
*  Attempt to RLOCK() with optional retry
*
*  Parameter:
*     nWaitSeconds - Optional time in seconds to retry operation, defaults
*                    to NET_SECS
*
*  Returns:
*     True if successful, false if not
*
*/
FUNCTION RecLock( nSeconds )
   
   LOCAL lForever          // Retry forever?

   DEFAULT nSeconds TO NET_SECS

   IF RLOCK()
      RETURN ( .T. )       // NOTE
   ENDIF

   lForever := ( nSeconds == 0 )

   DO WHILE ( lForever .OR. ( nSeconds > 0 ) )
      
      IF RLOCK()
         RETURN ( .T. )    // NOTE
      ENDIF

      INKEY( NET_WAIT )    // Wait 1/2 second
      nSeconds -= NET_WAIT

   ENDDO

   RETURN ( .F. )          // Not locked
Você pode estudá-lo e fazer adaptações para o teu próprio uso.
Boa sorte!

Re: Erro em abertura de rede

Enviado: 18 Ago 2010 14:38
por Josmar dos Santos
OK Alexsts, deu pra ficar bem claro...!
Valew pela aula ...
abraços

Josmar
:xau