Discussion:
Getnextmodified deadlock
(too old to reply)
Kovács András
2004-11-12 23:05:02 UTC
Permalink
Hi!

I can't solve this problem. In my program, in one place with one table, the
saving procedure somtimes goes into a loop with a Getnextmodified, wich gives
back the same record numer witch it was called. I use table buffering with
transactions.
Here is a part of code which makes the problem:
nActRec = GETNEXTMODIFIED(0, lcAlias)
DO WHILE nActRec <> 0
GO nActRec IN (lcAlias)
IF This.NetConflict(lcAlias, nActRec, "T") && Checks for fields
Oldval()<>Curval()
ROLLBACK
RETURN .F.
ENDIF
nActRec = GETNEXTMODIFIED(nActRec, lcAlias)
ENDDO

Here the nActRec= GETNEXTMODIFIED(nActRec,lcAlias) gives back the same value
(for example: 6), and can't step out the cicle.
I use VFP 8 with SP1.

How can it be?
Thank you,
András Kovács, Hungary
Dennis Longfellow
2004-11-13 00:02:48 UTC
Permalink
András,

From the looks of your code, you are using a transaction. If so, I assume
that you already have an END TRANSACTION somewhere in the code that we are
not seeing. I modified your code with a TABLEUPDATE(). I think that will
fix your problem. If you have a TABLEUPDATE() somewhere else in the code,
you should comment it out or remove it.

"Kov�cs Andr�s" <***@uw.hu> wrote in message news:316C9729-1B2D-4097-A340-***@microsoft.com...

<snipped>
Post by Kovács András
nActRec = GETNEXTMODIFIED(0, lcAlias)
DO WHILE nActRec <> 0
GO nActRec IN (lcAlias)
IF This.NetConflict(lcAlias, nActRec, "T") && Checks for fields
Oldval()<>Curval()
ROLLBACK
RETURN .F.
ENDIF
<new code follows:>
IF !TABLEUPDATE(.F.)
ROLLBACK
RETURN .F.
ENDIF
Post by Kovács András
nActRec = GETNEXTMODIFIED(nActRec, lcAlias)
ENDDO
Here the nActRec= GETNEXTMODIFIED(nActRec,lcAlias) gives back the same value
(for example: 6), and can't step out the cicle.
<sipped>

Until you issue the TABLEUPDATE(), the GETNEXTMODIFIED(nActRec,lcAlias) will
continue to find the modified record.

Incidentally, you could combine the IF ... ENDIF statements as follows:

IF This.NetConflict(lcAlias, nActRec, "T") AND !TABLEUPDATE(.F.)
ROLLBACK
RETURN .F.
ENDIF

Finally, I don't know your complete code for this, the above may not be
exactly what you need, but I think it points you in the right direction.

Hope that helps,

Dennis Longfellow
Anders Altberg
2004-11-15 12:16:56 UTC
Permalink
András

The syntax is
OLDVAL(cExpression [, cTableAlias | nWorkArea])
CURVAL(cExpression [, cTableAlias | nWorkArea])

Use ALL two parameters at all times if you want to be sure what you're
really checking.

-Anders
Post by Kovács András
Hi!
I can't solve this problem. In my program, in one place with one table, the
saving procedure somtimes goes into a loop with a Getnextmodified, wich gives
back the same record numer witch it was called. I use table buffering with
transactions.
nActRec = GETNEXTMODIFIED(0, lcAlias)
DO WHILE nActRec <> 0
GO nActRec IN (lcAlias)
IF This.NetConflict(lcAlias, nActRec, "T") && Checks for fields
Oldval()<>Curval()
ROLLBACK
RETURN .F.
ENDIF
nActRec = GETNEXTMODIFIED(nActRec, lcAlias)
ENDDO
Here the nActRec= GETNEXTMODIFIED(nActRec,lcAlias) gives back the same value
(for example: 6), and can't step out the cicle.
I use VFP 8 with SP1.
How can it be?
Thank you,
András Kovács, Hungary
Mark
2004-11-17 09:54:02 UTC
Permalink
Hi András,
The logics of your code are somewhat twisted. It should be something like
this:

BEGIN TRANSACTION
lGoOn = .T.
nActRec = GETNEXTMODIFIED(0, lcAlias)
DO WHILE nActRec <> 0 AND lGoOn
GO nActRec IN (lcAlias)
IF This.NetConflict(lcAlias, nActRec, "T") && Checks for fields
Oldval()<>Curval()
lGoOn = .F.
ELSE
=TABLEUPDATE(yourParameters)
ENDIF
nActRec = GETNEXTMODIFIED(nActRec, lcAlias)
ENDDO

IF lGoOn
END TRANSACTION
ELSE
ROLLBACK
= TABLEREVERT(.T.)
ENDIF

hth

Mark
Post by Kovács András
Hi!
I can't solve this problem. In my program, in one place with one table, the
saving procedure somtimes goes into a loop with a Getnextmodified, wich gives
back the same record numer witch it was called. I use table buffering with
transactions.
nActRec = GETNEXTMODIFIED(0, lcAlias)
DO WHILE nActRec <> 0
GO nActRec IN (lcAlias)
IF This.NetConflict(lcAlias, nActRec, "T") && Checks for fields
Oldval()<>Curval()
ROLLBACK
RETURN .F.
ENDIF
nActRec = GETNEXTMODIFIED(nActRec, lcAlias)
ENDDO
Here the nActRec= GETNEXTMODIFIED(nActRec,lcAlias) gives back the same value
(for example: 6), and can't step out the cicle.
I use VFP 8 with SP1.
How can it be?
Thank you,
András Kovács, Hungary
Kovács András
2004-11-23 09:59:06 UTC
Permalink
Hi!

Thank you for your answers, but moving the Tabaleupdate to to the Do While
didn't help. Sorry if I posted a bit short part of the code. My saving
routine is based on the FoxHelp style, and it wordks fine in all of my
program, it is called from nearly hundred places, and I have problems only in
one form.
The question is, how can the GETNEXTMODIFIED() give back the _SAME_ value
in a modified table (before the Tableupdate and the End Transaction)?

The problem is only with one table, but it doesn't look corrupted, and a
reindex doesn't help neither.

Thanks for your help,
Kovács András
Mark
2004-11-25 10:15:07 UTC
Permalink
Hi András,
I tried the code below and it works fine for me. Hence, it seems as if your
checking function moves the record pointer and gives you the SAME value for
GETNEXTMOFIED() over and over again.


Local nNextRecord, lGoOn

cOldMultilocks = Set("Multilocks")
Set Multilocks On

If !File("curdemo.dbf")
CREATE Table curdemo (fruit C(20))

INSERT INTO curdemo (fruit) VALUES ("Apples")
INSERT INTO curdemo (fruit) VALUES ("Oranges")
INSERT INTO curdemo (fruit) VALUES ("Grapes")
INSERT INTO curdemo (fruit) VALUES ("Bananas")
INSERT INTO curdemo (fruit) VALUES ("Pears")
INSERT INTO curdemo (fruit) VALUES ("Cherries")
INSERT INTO curdemo (fruit) VALUES ("Peaches")
INSERT INTO curdemo (fruit) VALUES ("Cherries - Red")
INSERT INTO curdemo (fruit) VALUES ("Cherries - Black")
INSERT INTO curdemo (fruit) VALUES ("Bananas - Green")
INSERT INTO curdemo (fruit) VALUES ("Peaches - White")
INSERT INTO curdemo (fruit) VALUES ("Peaches -Yellow")
Else
Use CurDemo in 0
Endif

= CursorSetProp("Buffering",5)
Locate

oForm1=NEWOBJECT("form1")
oForm1.Show
READ EVENTS
RETURN

DEFINE CLASS form1 AS Form

Caption = "Fruit Shop"
Name = "Form1"

Add Object Grid1 AS oGrid
Add Object Command1 AS oCommand

PROCEDURE Unload
Set Multilocks &cOldMultiLocks
CLOSE ALL
CLEAR EVENTS
ENDPROC

ENDDEFINE


DEFINE CLASS oGrid AS Grid

Left = 20
Top = 50
Width = 210
RowSourceType = 2
RowSource = "CurDemo"

ENDDEFINE

DEFINE CLASS oCommand AS CommandButton
Left = 20
Top = 20

PROCEDURE Click()
Begin TransAction
lGoon = .T.
nNextRecord = GetNextModified(0)
Do While nNextRecord > 0 and lGoOn = .T.
Goto nNextRecord
Wait Window + Transform(nNextRecord)
&& place here your data checking and if failing lGoOn = .F.
nNextRecord = GetNextModified(nNextRecord)
Enddo
If lGoOn
End TransAction
=TableUpdate(.T.,.T.)
Else
RollBack
=TableRevert(.T.)
EndIf

ThisForm.Refresh()
ENDPROC

ENDDEFINE

HTH
Mark
Post by Kovács András
Hi!
Thank you for your answers, but moving the Tabaleupdate to to the Do While
didn't help. Sorry if I posted a bit short part of the code. My saving
routine is based on the FoxHelp style, and it wordks fine in all of my
program, it is called from nearly hundred places, and I have problems only in
one form.
The question is, how can the GETNEXTMODIFIED() give back the _SAME_ value
in a modified table (before the Tableupdate and the End Transaction)?
The problem is only with one table, but it doesn't look corrupted, and a
reindex doesn't help neither.
Thanks for your help,
Kovács András
Loading...