[Zope] How to prevent concurrent access to the same object?

Alexei Ustyuzhaninov aiu@quorus-ms.ru
Mon, 11 Feb 2002 09:41:14 +0500


Richard Barrett wrote:

> At 20:40 08/02/2002 +0500, you wrote:

...

>> Well, let me share my story. I have a zope product which should be an 
>> editor of some special files. The main window of the editor is divided 
>> into two frames. The left frame is a menu which allows the user to 
>> choose different views of the file. After choosing an option in the 
>> menu the corresponding view will be shown in the right frame. 
>> Generation of the view takes some time on the server and during this 
>> time the user can choose another option in the menu. This will fire up 
>> another transaction on the server which may be inconsistent with the 
>> unfinished previous one. The reason is that both transactions affect 
>> the same file which is not protected by the zope supervision.
>>
>> To prevent this situation I need to lock the second transaction untill 
>> the first one will finish. And because both transactions perform as 
>> separate unix processes I decided to use semaphores to synchronize 
>> them.  A two-state semaphore is linked to every editable file. Ideally 
>> on entry a process waits until the corresponding semaphore be turned 
>> off, then turns it on itself, and turns off on entry. But this doesn't 
>> work in life. The second process never gets the semaphore turned off. 
>> Seems like  it locks the first process some other way and whole system 
>> is clinched. And that's what is peculiar for me in zope: how (and why) 
>> future transactions affect the previous ones?
> 
> 
> I'm assuming these special files are in the host OS (UNIX ?) file system.
> 
> Let me suggest the following approach:
> 
> 1. if you do not already have this, have a surrogate object in the ZODB 
> for each of your special files in the file system. You can then use the 
> transactability of ZODB over such objects to protect the external resource.
> 
> 2. Have an integer attribute on these objects.
> 
> 3. Immediately your server side code starts to process a request which 
> changes the contents of the external file have it change the surrogate 
> object attribute: increment it for instance.
> 
> 4. This will create a write lock over the surrogate and in effect over 
> the external file.
> 
> 5. Any other transaction attempting to change the attribute will then be 
> rolled back and retried. If all of your code plays together and always 
> tries to modify the surrogate attribute first then multiple updates of 
> the proxyied file are prevented.
> 
> 6. Arrange all of the processing of a file to be performed while the 
> lock is held, that is before the response is sent back to the browser 
> for the request.
> 
> 7. When you return a response to the browser, you can include the 
> identity of the surrogate object and the value of the integer attribute 
> on it associated with the file as a hidden input fields in a form which 
> is used to make the user processing request.
> 
> 8. If when the user selects an option (view of the file) this value is 
> returned, it can be compared with the value of the object attribute when 
> the request is received. If they do not match then your code can decide 
> on whether to reject the processing request and return the revised data 
> or do the requested processing.

Good solution, thanks. Though it doesn't seem to be effective because of 
continuous retries and rollbacks.

-- 
Alexei