[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