Programación en Red Local

Programación en Red Local

Postby Manuel Aranda » Fri Jan 13, 2012 9:33 pm

Desde hace muchos años (Desde Clipper) vengo arrastrando la siguiente función para modificar/añadir registros a un fichero en red local. La verdad es que siempre ha funcionado correctamente sin ningún problema en programas clipper y programas clipper/fivewin con nueve o diez usuarios trabajando simultáneamente. Sin embargo con fivewin+xHarbour estoy teniendo algún problema de duplicidad de registros y desaparición de uno que otro registro cuando se trabaja en red local sin explicación aparente, y sólo con dos o tres usuarios como mucho. No sé por donde tirar ni si el problema es esta función, la red local (me pasa en varias redes distintas) u otra causa, pero lo cierto es que este asunto me tiene bastante preocupado pues es un problema bastante grave y desconcertante.
Cualquier ayuda o sugerencia será bien recibida.

Code: Select all  Expand view  RUN

.........................
.........................
      //
      IF TRABAJA->(!RecLock(5))
         TONE(400,2)
         TONE(200,2)
         //
         IF lNuevo
            MsgStop("No es posible añadir el registro;inténtelo más tarde, por favor.")
         ELSE
            MsgStop("No es posible la modificación;inténtelo más tarde, por favor.")
         ENDIF
         //
      ELSE
         //
         TRABAJA->NOMTRA    = cNomTra        
         TRABAJA->POSTAL    = cPostal
         TRABAJA->LOCA      = cLoca
         TRABAJA->PROVIN    = cProvin
         TRABAJA->TELEFONO  = cTelefono
         //
         TRABAJA->(DbRunLock())
         TRABAJA->(DbCommit())
         //
      ENDIF
      //
.............................
.............................
#include "Common.ch"
#define NET_WAIT     0.5   // Seconds to wait between between retries
#define NET_SECS     2     // Number of seconds to continue retry
   
**********************************************      
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. )  
 
Un saludo,
Manuel

xH 1.2.3, FWH 23.07 32 bits, BC++ 7.4, xVerce CW 1.0, PellesC
User avatar
Manuel Aranda
 
Posts: 604
Joined: Wed Oct 19, 2005 8:20 pm
Location: España

Re: Programación en Red Local

Postby FiveWiDi » Fri Jan 13, 2012 11:12 pm

Manuel Aranda wrote:
Code: Select all  Expand view  RUN

.........................
.........................
      //
      IF TRABAJA->(!RecLock(5))
         TONE(400,2)
         TONE(200,2)
         //
         IF lNuevo
            MsgStop("No es posible añadir el registro;inténtelo más tarde, por favor.")
         ELSE
            MsgStop("No es posible la modificación;inténtelo más tarde, por favor.")
         ENDIF
         //
      ELSE
         //
         TRABAJA->NOMTRA    = cNomTra        
         TRABAJA->POSTAL    = cPostal
         TRABAJA->LOCA      = cLoca
         TRABAJA->PROVIN    = cProvin
         TRABAJA->TELEFONO  = cTelefono
         //
         TRABAJA->(DbRunLock())
         TRABAJA->(DbCommit())
         //
      ENDIF
      //
.............................
.............................
#include "Common.ch"
#define NET_WAIT     0.5   // Seconds to wait between between retries
#define NET_SECS     2     // Number of seconds to continue retry
   
**********************************************      
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. )  
 


Manuel,

Reclok() a mi modo de ver creo que está bien. Lo que no veo claro que esté bien es el código donde se está usando, me explico.

Segun el código que veo (no se si faltan trozos), no estás haciendo ningun DbAppend() ni ningún LOCATE, y además desde que se intenta bloquear el registro hasta que se consigue grabarlo no se ha actualizado ninguna variable de las que grabas, es decir: puedes estar intentanto boquear un registro (desde el puesto A) que en otro puesto de trabajo (B) se está actualizando. Con lo cual cuando desde el otro puesto (B) se actualiza y se libera el registro, entra en acción (A) sobreescribiendo el registro actualizado por (B).

Yo por ejemplo, uso referencias únicas guardadas en una DBF del sistema, cuando consigo bloquear el registro de la DBF de trabajo, es cuando obtengo la nueva referfencia; eso para las altas. Para las modificaciones, antes de editar miro si está borrado, en caso contrario una vez bloqueado busco el código que quiero 'updatear' por si existe en otro registro y finalmente el último puesto que graba es lo que queda.

Pero todo esto sin ver toda la rutina que usas para modifidcar/añadir registros.
Un Saludo
Carlos G.

FiveWin 24.02 + Harbour 3.2.0dev (r2403071241), BCC 7.7 Windows 10
FiveWiDi
 
Posts: 1190
Joined: Mon Oct 10, 2005 2:38 pm

Re: Programación en Red Local

Postby surGom » Sat Jan 14, 2012 10:49 am

Hola Manuel mira desde que aprendi algo de esto uso unos programas de Rick Spencer y nunca me dieron problemas fijate si te sirven:

Code: Select all  Expand view  RUN




******************************************************************************
/***
* NetTryUI.prg
*
* Una versi¢n de NetTry() que permite pasar un segundo codeblock
* y usarlo para preguntar si se desea continuar o no. Esta versi¢n
* lo reintenta hasta que este segundo codeblock devuelve .T.
*/


FUNCTION NetTryUI(nSeconds, bAction, bRetryUI)

LOCAL lSuccess, lRetry

  REPEAT
    IF !(lSuccess := NetTry(nSeconds, bAction))
      lRetry := Eval(bRetryUI)
    ENDIF
  UNTIL lSuccess .OR. !lRetry

RETURN lSuccess


*****************************************************************************
FUNCTION NetTry( nSeconds, bAction )

LOCAL lForever, lSuccess

  lForever := (nSeconds == NIL .OR. nSeconds == 0)
  DO WHILE !(lSuccess := Eval(bAction)) .AND. ;
            (lForever .OR. nSeconds > 0)

    InKey(.5)           // Esperar medio segundo
    nSeconds := nSeconds - .5
  ENDDO

RETURN lSuccess
*****************************************************************************
 
.

Y la forma de llamarla usando database (reemplazar un dato existente

Code: Select all  Expand view  RUN

FUNCTION reviso(odbf)                               &&bloquear registro en un objeto database
local exito
if exito:= NetTryUI(2,                                             ;
               {||odbf:reclock(), !neterr()  },;
               {||alert("Registro bloqueado ¨REINTENTAMOS?",{"SI","NO"}) == 1})
endif
return exito
 


agregar

Code: Select all  Expand view  RUN

FUNCTION yapar(odbf)
local exito
if exito := NetTryUI(2,                                             ;
               {||odbf:blank(),odbf:append(), !neterr()  },;
               {||alert("¨REINTENTAMOS?",{"SI","NO"}) == 1})
endif
return exito
 


y para uso directo de bases dbf

Code: Select all  Expand view  RUN

*funcion que trabaja sobre la base*/
FUNCTION revbase()                            &&bloquear registro de una base de datos directamente
local exito
if exito:= NetTryUI(2,                                             ;
               {||rlock(), !neterr()  },;
               {||alert("Registro bloqueado ¨REINTENTAMOS?",{"SI","NO"}) == 1})
endif
return exito
 


Espero sea de utilidad

Luis
surGom
 
Posts: 640
Joined: Wed Oct 19, 2005 12:03 pm

Re: Programación en Red Local

Postby surGom » Sat Jan 14, 2012 10:54 am

Un ejemplo con database

IF lNuevo
odata:append()
ENDIF
if reviso(odata)
odata:save()
odata:commit()
odata:unlock()
endif

Luis
surGom
 
Posts: 640
Joined: Wed Oct 19, 2005 12:03 pm

Re: Programación en Red Local

Postby hmpaquito » Sat Jan 14, 2012 12:07 pm

Manuel,

Yo tambien herede un rec_lock() desde clipper y sin problemas: creo que es igual al tuyo.
Lo que yo nunca hago es poner tiempo al "intento" de bloqueo: siempre pongo 0: se debe bloquear si o si.

Creo que tu problema sea otro y no tenga qaue ver con el reclock(): algun seek con el order erroneo o algo asi.

Saludos
hmpaquito
 
Posts: 1482
Joined: Thu Oct 30, 2008 2:37 pm

Re: Programación en Red Local

Postby Manuel Aranda » Sat Jan 14, 2012 1:16 pm

Primero que nada agradeceros a los tres vuestras respuestas, pues ya tengo material por donde empezar a mirar.
Carlos, voy a empezar a probar con la pista que me has dado. Me explico. Tengo una misma rutina para modificar/añadir un registro y dependiendo si es un registro a añadir o modificar hago el DbAppend():
//
IF lNuevo
TRABAJA->(DbAppend())
ENDIF
//
Pues bien, resulta que DbAppend() lo estaba haciendo con anteoridad, sin bloquear el fichero (Abriendo el fichero como Shared te permite añadir el registro sin bloquearlo, no así el modificarlo). Creo que por ahí puede venir el problema. He modificado la rutina y voy a observar el comportamiento.

Muchas gracias a todos.
Un saludo,
Manuel

xH 1.2.3, FWH 23.07 32 bits, BC++ 7.4, xVerce CW 1.0, PellesC
User avatar
Manuel Aranda
 
Posts: 604
Joined: Wed Oct 19, 2005 8:20 pm
Location: España

Re: Programación en Red Local

Postby acuellar » Sat Jan 14, 2012 1:46 pm

Manuel yo lo hago asi:
Code: Select all  Expand view  RUN

Function Aumenta(oDBF)
   Do While .T.
     IF oDBF:Lock()
        oDBF:Load()
        oDBF:CORRELATIVO+=1
        oDBF:Save()
        oDBF:COMMIT()
        oDBF:Lock()
        Exit
     Else
        Inkey(0.4)
     EndIf
   EndDo
Return Ni

*Luego que retorna de la funcion
 oDBF:unLock()
 


Funciona perfecto.

Espero te sirva

Saludos,

Adhemar
Saludos,

Adhemar C.
User avatar
acuellar
 
Posts: 1644
Joined: Tue Oct 28, 2008 6:26 pm
Location: Santa Cruz-Bolivia

Re: Programación en Red Local

Postby Manuel Aranda » Sun Jan 15, 2012 8:43 am

Adhemar, muchas gracias.
Un saludo,
Manuel

xH 1.2.3, FWH 23.07 32 bits, BC++ 7.4, xVerce CW 1.0, PellesC
User avatar
Manuel Aranda
 
Posts: 604
Joined: Wed Oct 19, 2005 8:20 pm
Location: España

Re: Programación en Red Local

Postby Armando » Sun Jan 15, 2012 5:02 pm

Adhemar:

Solo para salir de mi duda !

acuellar wrote:Manuel yo lo hago asi:
Code: Select all  Expand view  RUN

Function Aumenta(oDBF)
   Do While .T.
     IF oDBF:Lock()
        oDBF:Load()
        oDBF:CORRELATIVO+=1
        oDBF:Save()
        oDBF:COMMIT()
        oDBF:Lock()
        Exit
     Else
        Inkey(0.4)
     EndIf
   EndDo
Return Ni

*Luego que retorna de la funcion
 oDBF:unLock()
 

Adhemar


Qué caso tiene la línea oDbf:Lock dentro de un IF donde
la línea en cuestión se ejecuta cuando la DBF esta bloqueda?

En mi opinión la línea oDbf:COMMIT() hace lento el proceso y no siempre es necesaria
la línea para que se salve la información.

Saludos
SOI, s.a. de c.v.
estbucarm@gmail.com
http://www.soisa.mex.tl/
http://sqlcmd.blogspot.com/
Tel. (722) 174 44 45
Carpe diem quam minimum credula postero
User avatar
Armando
 
Posts: 3229
Joined: Fri Oct 07, 2005 8:20 pm
Location: Toluca, México

Re: Programación en Red Local

Postby Carlos Mora » Fri Jan 20, 2012 1:37 pm

Manuel,

veo que en tu código tienes
Code: Select all  Expand view  RUN

         TRABAJA->(DbRunLock())
         TRABAJA->(DbCommit())
 


lo que creo que debe ser
Code: Select all  Expand view  RUN

         TRABAJA->(DbCommit())
         TRABAJA->(DbRunLock())
 

Estás liberando el bloqueo ANTES DE ACTUALIZAR, lo que probablemente esté ocasionando los problemas. Puede que el commit no pueda actualizar porque ya se haya interpuesto otro lock.

UN saludo
Saludos
Carlos Mora
http://harbouradvisor.blogspot.com/
StackOverflow http://stackoverflow.com/users/549761/carlos-mora
“If you think education is expensive, try ignorance"
Carlos Mora
 
Posts: 989
Joined: Thu Nov 24, 2005 3:01 pm
Location: Madrid, España

Re: Programación en Red Local

Postby Manuel Aranda » Fri Jan 20, 2012 8:07 pm

Muchíiiisimas gracias, Carlos, puede que sea eso. No sé como no me he dado cuenta antes, con la de vueltas que le he dado.
Un saludo,
Manuel

xH 1.2.3, FWH 23.07 32 bits, BC++ 7.4, xVerce CW 1.0, PellesC
User avatar
Manuel Aranda
 
Posts: 604
Joined: Wed Oct 19, 2005 8:20 pm
Location: España


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 52 guests