How to prevent concurrent access to the same object?
Hi! Is it possible to make a zope object which doesn't allow simultaneous access to itself? I mean that if two users call methods of the same object then only one call will process at a time and the other one will wait untill the first call will finish. I tried to fix it up with unix semaphores but with no success. -- Alexei
At 10:15 06/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Hi!
Is it possible to make a zope object which doesn't allow simultaneous access to itself? I mean that if two users call methods of the same object then only one call will process at a time and the other one will wait untill the first call will finish. I tried to fix it up with unix semaphores but with no success.
Why do you want to do this so explicitly? I believe that Zope is inherently transactional and its own database updates are performed atomically with transaction commit, abort, rollback and retry apparatus built in. That said, you might want to ask how to plug in your own commit, rollback and retry code to zope's transaction commit and abort handlers if you problem is to control updating of some external database from zope code.
-- Alexei
_______________________________________________ Zope maillist - Zope@zope.org http://lists.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope-dev )
Richard Barrett wrote:
At 10:15 06/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Hi!
Is it possible to make a zope object which doesn't allow simultaneous access to itself? I mean that if two users call methods of the same object then only one call will process at a time and the other one will wait untill the first call will finish. I tried to fix it up with unix semaphores but with no success.
Why do you want to do this so explicitly?
I believe that Zope is inherently transactional and its own database updates are performed atomically with transaction commit, abort, rollback and retry apparatus built in.
BTW is there any method to monitor zope transactions? My experience is that they have quite peculiar behaviour.
That said, you might want to ask how to plug in your own commit, rollback and retry code to zope's transaction commit and abort handlers if you problem is to control updating of some external database from zope code.
I think you are right though I don't need sterling transactions in my objects. I need simple locks. So, could somebody advice how to plug in extra code to the zope transaction machinery? -- Alexei
At 11:12 08/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Richard Barrett wrote:
At 10:15 06/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Hi!
Is it possible to make a zope object which doesn't allow simultaneous access to itself? I mean that if two users call methods of the same object then only one call will process at a time and the other one will wait untill the first call will finish. I tried to fix it up with unix semaphores but with no success.
Why do you want to do this so explicitly?
I believe that Zope is inherently transactional and its own database updates are performed atomically with transaction commit, abort, rollback and retry apparatus built in.
BTW is there any method to monitor zope transactions? My experience is that they have quite peculiar behaviour.
How so peculiar?
That said, you might want to ask how to plug in your own commit, rollback and retry code to zope's transaction commit and abort handlers if you problem is to control updating of some external database from zope code.
I think you are right though I don't need sterling transactions in my objects. I need simple locks.
So, could somebody advice how to plug in extra code to the zope transaction machinery?
I do not know if it is still upd to date but you could try the material here: http://www.zope.org/Documentation/Developer/Models/ZODB/
-- Alexei
Richard Barrett wrote:
At 11:12 08/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Richard Barrett wrote:
At 10:15 06/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Hi!
Is it possible to make a zope object which doesn't allow simultaneous access to itself? I mean that if two users call methods of the same object then only one call will process at a time and the other one will wait untill the first call will finish. I tried to fix it up with unix semaphores but with no success.
Why do you want to do this so explicitly?
I believe that Zope is inherently transactional and its own database updates are performed atomically with transaction commit, abort, rollback and retry apparatus built in.
BTW is there any method to monitor zope transactions? My experience is that they have quite peculiar behaviour.
How so peculiar?
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?
That said, you might want to ask how to plug in your own commit, rollback and retry code to zope's transaction commit and abort handlers if you problem is to control updating of some external database from zope code.
I think you are right though I don't need sterling transactions in my objects. I need simple locks.
So, could somebody advice how to plug in extra code to the zope transaction machinery?
I do not know if it is still upd to date but you could try the material here: http://www.zope.org/Documentation/Developer/Models/ZODB/
Thanks. -- Alexei
At 20:40 08/02/2002 +0500, you wrote:
Richard Barrett wrote:
At 11:12 08/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Richard Barrett wrote:
At 10:15 06/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Hi!
Is it possible to make a zope object which doesn't allow simultaneous access to itself? I mean that if two users call methods of the same object then only one call will process at a time and the other one will wait untill the first call will finish. I tried to fix it up with unix semaphores but with no success.
Why do you want to do this so explicitly?
I believe that Zope is inherently transactional and its own database updates are performed atomically with transaction commit, abort, rollback and retry apparatus built in.
BTW is there any method to monitor zope transactions? My experience is that they have quite peculiar behaviour.
How so peculiar?
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.
That said, you might want to ask how to plug in your own commit, rollback and retry code to zope's transaction commit and abort handlers if you problem is to control updating of some external database from zope code.
I think you are right though I don't need sterling transactions in my objects. I need simple locks.
So, could somebody advice how to plug in extra code to the zope transaction machinery?
I do not know if it is still upd to date but you could try the material here: http://www.zope.org/Documentation/Developer/Models/ZODB/
Thanks.
-- Alexei
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
At 09:41 11/02/2002 +0500, Alexei Ustyuzhaninov wrote:
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.
I suppose you might be able to use an initial read of (as opposed to write to) an attribute on surrogate objects to let an incoming request determine that another transaction on the same object is in progress and provide a graceful response rather than retrying and failing. Other than buying a faster server I cannot suggest a way of making the approach you are using work any better. It sounds to me as though you need to restructure the problem. If you check the zope archives you'll find some posts from around the begining February on the subject '[Zope] timeout' which might be relevant. I'll forward copies to you.
-- Alexei
Richard Barrett wrote:
At 09:41 11/02/2002 +0500, Alexei Ustyuzhaninov wrote:
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.
I suppose you might be able to use an initial read of (as opposed to write to) an attribute on surrogate objects to let an incoming request determine that another transaction on the same object is in progress and provide a graceful response rather than retrying and failing.
Other than buying a faster server I cannot suggest a way of making the approach you are using work any better.
It sounds to me as though you need to restructure the problem. If you check the zope archives you'll find some posts from around the begining February on the subject '[Zope] timeout' which might be relevant. I'll forward copies to you.
Thanks again for your help. Probably the retry-rollback approach wouldn't be too wasteful in my case. The longest request is processed about 10 seconds and if we insert 3-second sleep between retries and if users won't have habit to send a new command until the previous one will be completed the overall performance shouldn't reduce much. Though it's a pity that such mechanisms as semaphores don't work in this case. -- Alexei
hi alexei, if you really want locking you can do it via a using a module as a shared namespace between zope threads to store lock variables. a simple example in most pseudcode inside a module SpecialAppFileLocks.py _lock_storage = {} _storage_lock = Lock() def get_lock(file_id): _storage_lock.acquire() file_lock = _locks.get(file_id) if not file_lock: _lock_storage[file_id]=Lock() _storage_lock.release() file_lock.aqcuire() def release_lock(file_id): _storage_lock.acquire() file_lock = _lock_storage.get(file_id) file_lock.release() _storage_lock.release() probably best to wrap the storage locking code in a try: finally clause. hth. kapil On Friday 08 February 2002 07:40 am, Alexei Ustyuzhaninov wrote:
Richard Barrett wrote:
At 11:12 08/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Richard Barrett wrote:
At 10:15 06/02/2002 +0500, Alexei Ustyuzhaninov wrote:
Hi!
Is it possible to make a zope object which doesn't allow simultaneous access to itself? I mean that if two users call methods of the same object then only one call will process at a time and the other one will wait untill the first call will finish. I tried to fix it up with unix semaphores but with no success.
Why do you want to do this so explicitly?
I believe that Zope is inherently transactional and its own database updates are performed atomically with transaction commit, abort, rollback and retry apparatus built in.
BTW is there any method to monitor zope transactions? My experience is that they have quite peculiar behaviour.
How so peculiar?
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?
That said, you might want to ask how to plug in your own commit, rollback and retry code to zope's transaction commit and abort handlers if you problem is to control updating of some external database from zope code.
I think you are right though I don't need sterling transactions in my objects. I need simple locks.
So, could somebody advice how to plug in extra code to the zope transaction machinery?
I do not know if it is still upd to date but you could try the material here: http://www.zope.org/Documentation/Developer/Models/ZODB/
Thanks.
Alexei Ustyuzhaninov writes:
Is it possible to make a zope object which doesn't allow simultaneous access to itself? You may have a look at my product "SharableResource":
Dieter Maurer wrote:
Alexei Ustyuzhaninov writes:
Is it possible to make a zope object which doesn't allow simultaneous access to itself? You may have a look at my product "SharableResource":
Thanks. Unfortunately RLock-based methods don't work in this situation (in linux at least) because concurrent transactions are executed in separate processes, not in threads of a single process. -- Alexei
Alexei Ustyuzhaninov writes:
Alexei Ustyuzhaninov writes:
Is it possible to make a zope object which doesn't allow simultaneous access to itself? You may have a look at my product "SharableResource":
Thanks. Unfortunately RLock-based methods don't work in this situation (in linux at least) because concurrent transactions are executed in separate processes, not in threads of a single process. I do not believe you. If you were right, then the Linux thread implementation were severely broken.
Locks are intended to coordinate concurrent threads. There is no other purpose for them. I am sure they work even though Linux implements threads by processes. Dieter
Dieter Maurer wrote:
Alexei Ustyuzhaninov writes:
Alexei Ustyuzhaninov writes:
Is it possible to make a zope object which doesn't allow simultaneous access to itself? You may have a look at my product "SharableResource":
Thanks. Unfortunately RLock-based methods don't work in this situation (in linux at least) because concurrent transactions are executed in separate processes, not in threads of a single process. I do not believe you. If you were right, then the Linux thread implementation were severely broken.
Locks are intended to coordinate concurrent threads. There is no other purpose for them. I am sure they work even though Linux implements threads by processes.
Well, of course I had to try your product before comment, sorry. Probably zope kernel is designed in such way that it can use RLock to synchronize its child processes. But generally RLock is inappropriate for this purpose in python. Take a look at this test for example: 09:50:33 aleks@aiu:~/testRLock $ cat test.py import os import threading import time lock=threading.RLock() if os.fork()==0: # Child process time.sleep(1) lock.acquire() print "Process",os.getpid(),": the child acquired the lock" else: # Parent process lock.acquire() print "Process",os.getpid(),": the parent acquired the lock" time.sleep(5) lock.release() print "Process",os.getpid(),"released the lock" 09:52:46 aleks@aiu:~/testRLock $ python test.py Process 6164 : the parent acquired the lock Process 6165 : the child acquired the lock Process 6165 released the lock Process 6164 released the lock -- Alexei
Alexei Ustyuzhaninov writes:
But generally RLock is inappropriate for this purpose in python. Take a look at this test for example:
09:50:33 aleks@aiu:~/testRLock $ cat test.py import os import threading import time
lock=threading.RLock() if os.fork()==0: # Child process time.sleep(1) lock.acquire() print "Process",os.getpid(),": the child acquired the lock" else: # Parent process lock.acquire() print "Process",os.getpid(),": the parent acquired the lock" time.sleep(5) lock.release() print "Process",os.getpid(),"released the lock"
09:52:46 aleks@aiu:~/testRLock $ python test.py Process 6164 : the parent acquired the lock Process 6165 : the child acquired the lock Process 6165 released the lock Process 6164 released the lock Please retry this with threads!
While Linux uses processes to implement threads, these processes are more tightly coupled than those created by "fork". A fork'ed process has its own address space and its own independent resources (such as locks). Threads, on the other hand, share the same address space and the same resources. Locks will synchronize threads but not (independent) processes. Dieter
Dieter Maurer wrote: ...
Please retry this with threads!
While Linux uses processes to implement threads, these processes are more tightly coupled than those created by "fork".
A fork'ed process has its own address space and its own independent resources (such as locks). Threads, on the other hand, share the same address space and the same resources.
Locks will synchronize threads but not (independent) processes.
Yes, you are right. I couldn't even suppose that threads of the same process have different pids. Thank you for the explanation. -- Alexei
Alexei Ustyuzhaninov wrote:
Well, of course I had to try your product before comment, sorry. Probably zope kernel is designed in such way that it can use RLock to synchronize its child processes.
But generally RLock is inappropriate for this purpose in python. Take a look at this test for example:
09:50:33 aleks@aiu:~/testRLock $ cat test.py import os import threading import time
lock=threading.RLock() if os.fork()==0: # Child process time.sleep(1) lock.acquire() print "Process",os.getpid(),": the child acquired the lock" else: # Parent process lock.acquire() print "Process",os.getpid(),": the parent acquired the lock" time.sleep(5) lock.release() print "Process",os.getpid(),"released the lock"
09:52:46 aleks@aiu:~/testRLock $ python test.py Process 6164 : the parent acquired the lock Process 6165 : the child acquired the lock Process 6165 released the lock Process 6164 released the lock
Alexei, I'm by no means an expert, but are you sure that you can use os.fork() for what you want to do? This works for me (sorry for the wrapping) import threading import time my_lock = threading.RLock() def my_thread(my_time=5, id='', lock=0): if lock: my_lock.acquire() time.sleep(my_time) if lock: my_lock.release() print "%s thread is finished" % id slow = 5 fast = 1 t1 = threading.Thread(target=my_thread,kwargs={'my_time':slow, 'id':'slow'}) t2 = threading.Thread(target=my_thread,kwargs={'my_time':fast, 'id':'fast'}) t1.start() t2.start() t1 = threading.Thread(target=my_thread,kwargs={'my_time':slow, 'id':'slow_with_lock', 'lock':1}) t2 = threading.Thread(target=my_thread,kwargs={'my_time':fast, 'id':'fast_with_lock', 'lock':1}) t1.start() t2.start() Result: ~/work/pythontests/threadtest > python mythreadtest.py fast thread is finished slow thread is finished slow_with_lock thread is finished fast_with_lock thread is finished
participants (5)
-
Alexei Ustyuzhaninov -
Dieter Maurer -
kapil thangavelu -
Oliver Bleutgen -
Richard Barrett