I starting looking at this again a few weeks ago when Mark Rivers reported a problem that Ben Franksen recognized as being this bug. I'm still deciding how best to fix it; this comment is just to record my conclusions to date, I'm not looking for feedback yet and I don't have code.
The scanOnceCallback() routine was added on the 3.16 branch by the dbscan-update branch to fix lp:1362362. However dbCA's scanComplete() routine that is the only user to date doesn't know whether the record was actually processed or not. I'm convinced that we need RPRO to solve this issue.
The only internal code that calls scanOnce() is recGblFwdLink(), which does so if RPRO is set at the end of record processing. In that particular case it doesn't matter if onceTask subsequently finds PACT==TRUE since its purpose has already been met — to have the record processed again, which someone else had already triggered. Thus for this usage the original simple scanOnce() API is fine.
The dbCa case is more complicated because the scanLinkOnce() routine that uses scanOnceCallback() gets called from a CA callback routine in the context of a CA thread. It can't know whether the record is busy or not at the time, and it can't take the record lock to go and look without risking deadlocks and probably affecting performance. However it can set a flag in the caLink object to indicate that a newly arrived value is waiting to be read by the record, so when this scanOnce request gets processed by onceTask it can set RPRO if the record is busy (PACT) and the flag indicates that the value from the link has not been read yet. Using RPRO guarantees that the record will reprocess when the current process cycle completes.
The flag is set in dbCA's scanLinkOnce(), when is it cleared? I originally assumed that would happen when the value gets read, but if the CP link that triggered the processing isn't read when the record processes, the flag could then remain set forever. That's no good, I need it to indicate that a scan is already queued up, so further queuing is unnecessary (CA is allowed to throw away monitor updates, we're just doing the same thing). That means we have to clear the flag in dbCA's scanComplete() routine (or it's replacement), i.e. just before we process the record or set its RPRO field. It must happen before in case a monitor comes in during processing.
I starting looking at this again a few weeks ago when Mark Rivers reported a problem that Ben Franksen recognized as being this bug. I'm still deciding how best to fix it; this comment is just to record my conclusions to date, I'm not looking for feedback yet and I don't have code.
------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- ------- -
The scanOnceCallback() routine was added on the 3.16 branch by the dbscan-update branch to fix lp:1362362. However dbCA's scanComplete() routine that is the only user to date doesn't know whether the record was actually processed or not. I'm convinced that we need RPRO to solve this issue.
The only internal code that calls scanOnce() is recGblFwdLink(), which does so if RPRO is set at the end of record processing. In that particular case it doesn't matter if onceTask subsequently finds PACT==TRUE since its purpose has already been met — to have the record processed again, which someone else had already triggered. Thus for this usage the original simple scanOnce() API is fine.
The dbCa case is more complicated because the scanLinkOnce() routine that uses scanOnceCallback() gets called from a CA callback routine in the context of a CA thread. It can't know whether the record is busy or not at the time, and it can't take the record lock to go and look without risking deadlocks and probably affecting performance. However it can set a flag in the caLink object to indicate that a newly arrived value is waiting to be read by the record, so when this scanOnce request gets processed by onceTask it can set RPRO if the record is busy (PACT) and the flag indicates that the value from the link has not been read yet. Using RPRO guarantees that the record will reprocess when the current process cycle completes.
The flag is set in dbCA's scanLinkOnce(), when is it cleared? I originally assumed that would happen when the value gets read, but if the CP link that triggered the processing isn't read when the record processes, the flag could then remain set forever. That's no good, I need it to indicate that a scan is already queued up, so further queuing is unnecessary (CA is allowed to throw away monitor updates, we're just doing the same thing). That means we have to clear the flag in dbCA's scanComplete() routine (or it's replacement), i.e. just before we process the record or set its RPRO field. It must happen before in case a monitor comes in during processing.