Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Transação x RLOCK()
Message
 
To
29/01/2002 22:20:35
General information
Forum:
Visual FoxPro
Category:
Databases,Tables, Views, Indexing and SQL syntax
Miscellaneous
Thread ID:
00612586
Message ID:
00612907
Views:
25
This message has been marked as the solution to the initial question of the thread.
Oi carlos,

Bom vê-lo por aqui! Bom para mim e certamente bom para a UT...

Bem, vou tentar responder sem questionar uma ou outra técnica, mas lhe apontando como eu implementaria esta questão. Na minha visão, o controle explícito dos bloqueios dá maior tranquilidade visto que o controle sobre eles é do programador e não implícito no controle de transação. Sendo assim, tentei bolar um exemplo para ver se é isso que você precisa. Criei um projeto com um PRG definindo uma classe OLEPUBLIC cujo código apresento abaixo. Alguns comentários importantes estão no código, inclusive sobre o FLUSH, que acho que seja particularmente útil nesta situação:
DEFINE CLASS Comp as Custom olepublic

  FUNCTION GetProximoCodigo()
  
    LOCAL lnNovoCodigo
    lnNovoCodigo = -1
    
    IF !USED("codigos")
      USE codigos IN 0 SHARED 
    ENDIF
    
    * Vamos tentar bloquear indefinidamente, assim nos livramos de 
    * configurações de SET REPROCESS eventualmente diferentes. Se vc quiser
    * pode adotar outra estratégia...
    DO WHILE NOT FLOCK()
    ENDDO
    
    REPLACE Codigos.Codigo WITH codigos.Codigo + 1 IN Codigos
    
    * Vamos atualizar o valor de retorno logo aqui que ainda temos o Lock
    lnNovoCodigo = Codigos.Codigo
    
    * O FLUSH aqui pode ajudar, visto que não precisamos nos preocupar com
    * questões de buffer do sistema operacional
    FLUSH
    
    * Tá resto do mundo... é teu!
    UNLOCK
    
    RETURN lnNovoCodigo
  
  ENDFUNC
ENDDEFINE
Ok, compile este projeto em uma MTDLL.

Vamos criar duas tabelas. Uma irá simular a tabela de códigos e outra usaremos para a saída dos testes. Para a tabela de códigos, vamos criá-la e já inicializá-la com um valor inicial, assim:
CREATE TABLE Codigos (Codigo I)
INSERT INTO Codigos VALUES (1)
Para a tabela de saídas (na qual colocaremos os códigos gerados), teremos o seguinte script:
CREATE TABLE Saida (Codigo I, IDComp C(5))
O campo "Codigo" será o código gerado e o campo "IDComp" será um identificador de qual instância do componente gerou o código.

Agora vamos supor um cenário de alta atualização. Para isso, abra duas sessões do VFP e execute o seguinte código simultâneamente, só tomando o cuidado de mudar o nome do identificador ("COMP1") em cada sessão:
DECLARE Sleep in WIN32API INTEGER
USE Saida SHARED

LOCAL loComp
loComp = CREATEOBJECT("comp.comp")
DO WHILE .T.
  INSERT INTO Saida VALUES (loComp.GetProximoCodigo(), "COMP1")
  IF LASTKEY() = 27
    EXIT
  ENDIF
  Sleep(1000)      && Pára por 1 segundo para dar oportunidade dos outros rodarem
ENDDO
Quando você cansar ou o espaço do seu disco rígido for para a cucuia ;-) dê um ESC em cada uma das sessões.
Basta agora verificarmos se houve alguma duplicação na geração; o que segundo os testes realizados na minha máquina, não ocorreu. Verifiquei da seguinte forma:
SELECT Codigo, COUNT(Codigo) as Ocorrencias ;
  FROM Saida ;
  GROUP BY Codigo HAVING Ocorrencias > 1
  INTO CURSOR Repetidos
Se aqui retornar algum registro, é pq repetiu uma numeração.

Espero que você consiga sanar estas questões. Também acho muito importante esse tipo de assunto.

Um abraço!
-----
Fabio Vazquez
http://www.fabiovazquez.com
Previous
Reply
Map
View

Click here to load this message in the networking platform