Bug #6392
buffer flush and validation when the external program gets deleted can cause unique index validation error
0%
History
#2 Updated by Constantin Asofiei about 2 years ago
This is a recreate of a buffer being flushed when the external program gets deleted.
The table:
ADD TABLE "topic" AREA "Schema Area" DUMP-NAME "topic" ADD FIELD "f1" OF "topic" AS character FORMAT "x(8)" INITIAL "" POSITION 2 MAX-WIDTH 16 ORDER 10 ADD FIELD "f2" of "topic" as character FORMAT "x(8)" INITIAL "" POSITION 3 MAX-WIDTH 16 ORDER 20 ADD INDEX "idx1" ON "topic" AREA "Schema Area" UNIQUE INDEX-FIELD "f2" ASCENDING
First program (txp1.p
):
procedure proc0. create topic. assign topic.f1 = "123". // topic.f2 = "abc". end.
Second program (txp2.p
), run this:
for each topic: delete topic. end. def var i as int. def var h as handle. repeat transaction: run txp1.p persistent set h. run proc0 in h. message "here1". delete object h. run txp1.p persistent set h. run proc0 in h. message "here2". delete object h. run txp1.p persistent set h. run proc0 in h. message "here3". delete object h. leave. end.
Note how in txp1.p
the field part of the unique index is not touched. Thus, the 'endBatch' call will not validate the record. This will be performed when the external program gets deleted (and it seems OE does it like this, too).
In FWD, this abends the ProcedureManager.delete
call; I've tried wrapping the 'delete' and 'scopeDeleted' calls in ErrorManager.nestedSilent(() -> target.deleted());
, like this:
### Eclipse Workspace Patch 1.0 #P p2j6129a Index: src/com/goldencode/p2j/util/ProcedureManager.java =================================================================== --- src/com/goldencode/p2j/util/ProcedureManager.java (revision 3608) +++ src/com/goldencode/p2j/util/ProcedureManager.java (working copy) @@ -2367,12 +2367,12 @@ // cleanup after the procedure for (Finalizable target : pdata.finalizables) { - target.deleted(); + ErrorManager.nestedSilent(() -> target.deleted()); } for (Scopeable target : pdata.scopeables) { - target.scopeDeleted(); + ErrorManager.nestedSilent(() -> target.scopeDeleted()); } // as the procedure no longer exists, delete the static resources @@ -3376,7 +3376,7 @@ wa.pendingResourceDelete = target; try { - ((Deletable) target).delete(); + ErrorManager.nestedSilent(() -> ((Deletable) target).delete()); } finally {
But is not enough, I think what's missing is a rollback in case of ValidationException.
#3 Updated by Constantin Asofiei about 2 years ago
The better recreate is this:
for each topic: delete topic. end. def var i as int. def var h as handle. repeat transaction i = 1 to 4: run txp1.p persistent set h. run proc0 in h. message "here1". delete object h. end.
When the repeat
loop iterates, it will trigger a flush which abends the program.
#4 Updated by Constantin Asofiei about 2 years ago
There is this interesting note here https://docs.progress.com/bundle/openedge-abl-reference-117/page/DELETE-PROCEDURE-statement.html :
Note that all buffers are validated before being disconnected (which might cause database write triggers to execute). If the validation fails, the DELETE PROCEDURE statement raises the ERROR condition and pends the deletion until the validation succeeds and all database write triggers have completed.
#5 Updated by Constantin Asofiei about 2 years ago
I've added a trigger, and this gets invoked before the proc0
internal procedure returns.
#6 Updated by Constantin Asofiei about 2 years ago
Constantin Asofiei wrote:
I've added a trigger, and this gets invoked before the
proc0
internal procedure returns.
But the actual flush does happen on the external program delete (when the buffer is disconnected).
#7 Updated by Constantin Asofiei about 2 years ago
- Status changed from New to WIP
- Assignee set to Constantin Asofiei
#8 Updated by Constantin Asofiei about 2 years ago
In the end I think the root cause was the fact that BufferManager.dirtyBuffer
was still referencing the deleted procedure's buffers. After I fixed this (plus the procedure delete code to not abend on error when deleting a resource), things look better).