|
Posted by Joshua Beall on 03/25/05 18:18
> But a double-submit is likely to come from separate Apache processes, so
> I don't see where the pid comes into the picture. If I reload a page and
> resend the post data, that POST request is going to be processed a second
> time most likely by a different httpd process. What you need to do is
> put a unique (you can use the uniqid function) in the actual transaction
> data and not allow the transaction if that token is already present in
> your datastore.
I'm with you so far, but here is the problem I am having. Let me preface
this by saying that, in retrospect, I did not solve this problem as
elegantly as I should have. At any rate, let P1 and P2 represent separate
parallel transactions. $key is the same in both processes.
P1: "Does token.status = 'locked' WHERE key=$key ?"
P2: "Does token.status = 'locked' WHERE key=$key ?"
P1: {Receives negative response}
P2: {Receives negative response}
P1: Updates token.status. = 'locked' WHERE key=$key
P2: Updates token.status. = 'locked' WHERE key=$key
P1: Processes transaction
P2: Processes transaction
Now in retrospect this was not the simplest way to do it, but it worked (and
here is where PID comes in): After P1 inserts the token in the database, it
checks again to see that it is inserted *and* that it is the owner (token
has a field for "owner"). Like this:
P1: Updates token.status = 'locked' && owner=getmypid() WHERE key=$key &&
owner = ''
P2: Updates token.status = 'locked' && owner=getmypid() WHERE key=$key &&
owner = ''
P1: Checks to see if token is locked and P1 is owner. If not, abort.
P2: Checks to see if token is locked and P2 is owner. If not, abort.
Now, whichever one of these exectues first will get the token. The other
will abort.
But you see that I need the PID (or some other unique identifier) so that
the script can identify itself, otherwise P1 and P2 might both in parallel
attempt to lock the token, and both would appear to have received the lock.
At any rate, I am realizing now as I talk this through that there were other
simpler methods for doing what I needed. Oh well. But for now I solved the
problem as described above.
Thanks for the input. When I got in to PHP I didn't anticipate carrying on
a casual conversation with the guy who invented it!
-Josh
[Back to original message]
|