Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
ZEO
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
ZEO
Commits
1e6c884c
Commit
1e6c884c
authored
Feb 18, 2008
by
Jim Fulton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Removed ThreadedAsync and (last?) vestiges of the old "non-async"
mode.
parent
b7d7570b
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
16 additions
and
286 deletions
+16
-286
src/CHANGES.txt
src/CHANGES.txt
+2
-0
src/ThreadedAsync/LoopCallback.py
src/ThreadedAsync/LoopCallback.py
+0
-147
src/ThreadedAsync/__init__.py
src/ThreadedAsync/__init__.py
+0
-19
src/ZEO/ClientStorage.py
src/ZEO/ClientStorage.py
+0
-3
src/ZEO/runzeo.py
src/ZEO/runzeo.py
+2
-2
src/ZEO/tests/zeoserver.py
src/ZEO/tests/zeoserver.py
+3
-4
src/ZEO/zrpc/connection.py
src/ZEO/zrpc/connection.py
+8
-106
src/ZEO/zrpc/server.py
src/ZEO/zrpc/server.py
+1
-2
src/ZODB/scripts/zodbload.py
src/ZODB/scripts/zodbload.py
+0
-3
No files found.
src/CHANGES.txt
View file @
1e6c884c
...
@@ -32,6 +32,8 @@ New Features
...
@@ -32,6 +32,8 @@ New Features
on datetimes or serials (TIDs). See
on datetimes or serials (TIDs). See
src/ZODB/historical_connections.txt.
src/ZODB/historical_connections.txt.
- Removed the ThreadedAsync module.
Bugs Fixed
Bugs Fixed
----------
----------
...
...
src/ThreadedAsync/LoopCallback.py
deleted
100644 → 0
View file @
b7d7570b
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Manage the asyncore mainloop in a multi-threaded app.
In a multi-threaded application, only a single thread runs the
asyncore mainloop. This thread (the "mainloop thread") may not start
the mainloop before another thread needs to perform an async action
that requires it. As a result, other threads need to coordinate with
the mainloop thread to find out whether the mainloop is running.
This module implements a callback mechanism that allows other threads
to be notified when the mainloop starts. A thread calls
register_loop_callback() to register interest. When the mainloop
thread calls loop(), each registered callback will be called with the
socket map as its first argument.
"""
import
asyncore
import
thread
# Zope pokes a non-None value into exit_status when it wants the loop()
# function to exit. Indeed, there appears to be no other way to tell
# Zope3 to shut down.
exit_status
=
None
_loop_lock
=
thread
.
allocate_lock
()
_looping
=
None
# changes to socket map when loop() starts
_loop_callbacks
=
[]
def
register_loop_callback
(
callback
,
args
=
(),
kw
=
None
):
"""Register callback function to be called when mainloop starts.
The callable object callback will be invokved when the mainloop
starts. If the mainloop is currently running, the callback will
be invoked immediately.
The callback will be called with a single argument, the mainloop
socket map, unless the optional args or kw arguments are used.
args defines a tuple of extra arguments to pass after the socket
map. kw defines a dictionary of keyword arguments.
"""
_loop_lock
.
acquire
()
try
:
if
_looping
is
not
None
:
callback
(
_looping
,
*
args
,
**
(
kw
or
{}))
else
:
_loop_callbacks
.
append
((
callback
,
args
,
kw
))
finally
:
_loop_lock
.
release
()
def
remove_loop_callback
(
callback
):
"""Remove a callback function registered earlier.
This is useful if loop() was never called.
"""
for
i
,
value
in
enumerate
(
_loop_callbacks
):
if
value
[
0
]
==
callback
:
del
_loop_callbacks
[
i
]
return
# Because of the exit_status magic, we can't just invoke asyncore.loop(),
# and that's a shame.
# The signature of asyncore.loop changed between Python 2.3 and 2.4, and
# this loop() has 2.4's signature, which added the optional `count` argument.
# Since we physically replace asyncore.loop with this `loop`, and want
# compatibility with both Pythons, we need to support the most recent
# signature. Applications running under 2.3 should (of course) avoid using
# the `count` argument, since 2.3 doesn't have it.
def
loop
(
timeout
=
30.0
,
use_poll
=
False
,
map
=
None
,
count
=
None
):
global
_looping
global
exit_status
exit_status
=
None
if
map
is
None
:
map
=
asyncore
.
socket_map
# This section is taken from Python 2.3's asyncore.loop, and is more
# elaborate than the corresponding section of 2.4's: in 2.4 poll2 and
# poll3 are aliases for the same function, in 2.3 they're different
# functions.
if
use_poll
:
if
hasattr
(
select
,
'poll'
):
poll_fun
=
asyncore
.
poll3
else
:
poll_fun
=
asyncore
.
poll2
else
:
poll_fun
=
asyncore
.
poll
# The loop is about to start: invoke any registered callbacks.
_loop_lock
.
acquire
()
try
:
_looping
=
map
while
_loop_callbacks
:
cb
,
args
,
kw
=
_loop_callbacks
.
pop
()
cb
(
map
,
*
args
,
**
(
kw
or
{}))
finally
:
_loop_lock
.
release
()
# Run the loop. This is 2.4's logic, with the addition that we stop
# if/when this module's exit_status global is set to a non-None value.
if
count
is
None
:
while
map
and
exit_status
is
None
:
poll_fun
(
timeout
,
map
)
else
:
while
map
and
count
>
0
and
exit_status
is
None
:
poll_fun
(
timeout
,
map
)
count
-=
1
_loop_lock
.
acquire
()
try
:
_looping
=
None
finally
:
_loop_lock
.
release
()
# Evil: rebind asyncore.loop to the above loop() function.
#
# Code should explicitly call ThreadedAsync.loop() instead of asyncore.loop().
# Most of ZODB has been fixed, but ripping this out may break 3rd party code.
# Maybe we should issue a warning and let it continue for a while (NOTE: code
# to raise DeprecationWarning was written but got commented out below; don't
# know why it got commented out). Or maybe we should get rid of this
# mechanism entirely, and have each piece that needs one run its own asyncore
# loop in its own thread.
##def deprecated_loop(*args, **kws):
## import warnings
## warnings.warn("""\
##ThreadedAsync.loop() called through sneaky asyncore.loop() rebinding.
##You should change your code to call ThreadedAsync.loop() explicitly.""",
## DeprecationWarning)
## loop(*args, **kws)
##
##asyncore.loop = deprecated_loop
asyncore
.
loop
=
loop
src/ThreadedAsync/__init__.py
deleted
100644 → 0
View file @
b7d7570b
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Manage the asyncore mainloop in a multi-threaded app.
$Id$
"""
from
LoopCallback
import
register_loop_callback
,
loop
,
remove_loop_callback
src/ZEO/ClientStorage.py
View file @
1e6c884c
...
@@ -369,7 +369,6 @@ class ClientStorage(object):
...
@@ -369,7 +369,6 @@ class ClientStorage(object):
# still be going on. This code must wait until validation
# still be going on. This code must wait until validation
# finishes, but if the connection isn't a zrpc async
# finishes, but if the connection isn't a zrpc async
# connection it also needs to poll for input.
# connection it also needs to poll for input.
assert
self
.
_connection
.
is_async
()
while
1
:
while
1
:
self
.
_ready
.
wait
(
30
)
self
.
_ready
.
wait
(
30
)
if
self
.
_ready
.
isSet
():
if
self
.
_ready
.
isSet
():
...
@@ -524,8 +523,6 @@ class ClientStorage(object):
...
@@ -524,8 +523,6 @@ class ClientStorage(object):
# handled in order.
# handled in order.
self
.
_info
.
update
(
stub
.
get_info
())
self
.
_info
.
update
(
stub
.
get_info
())
assert
conn
.
is_async
()
self
.
_handle_extensions
()
self
.
_handle_extensions
()
def
_handle_extensions
(
self
):
def
_handle_extensions
(
self
):
...
...
src/ZEO/runzeo.py
View file @
1e6c884c
...
@@ -34,6 +34,7 @@ Unless -C is specified, -a and -f are required.
...
@@ -34,6 +34,7 @@ Unless -C is specified, -a and -f are required.
# For the forseeable future, it must work under Python 2.1 as well as
# For the forseeable future, it must work under Python 2.1 as well as
# 2.2 and above.
# 2.2 and above.
import
asyncore
import
os
import
os
import
sys
import
sys
import
signal
import
signal
...
@@ -241,8 +242,7 @@ class ZEOServer:
...
@@ -241,8 +242,7 @@ class ZEOServer:
auth_realm
=
self
.
options
.
auth_realm
)
auth_realm
=
self
.
options
.
auth_realm
)
def
loop_forever
(
self
):
def
loop_forever
(
self
):
import
ThreadedAsync.LoopCallback
asyncore
.
loop
()
ThreadedAsync
.
LoopCallback
.
loop
()
def
handle_sigterm
(
self
):
def
handle_sigterm
(
self
):
log
(
"terminated by SIGTERM"
)
log
(
"terminated by SIGTERM"
)
...
...
src/ZEO/tests/zeoserver.py
View file @
1e6c884c
...
@@ -13,6 +13,7 @@
...
@@ -13,6 +13,7 @@
##############################################################################
##############################################################################
"""Helper file used to launch a ZEO server cross platform"""
"""Helper file used to launch a ZEO server cross platform"""
import
asyncore
import
os
import
os
import
sys
import
sys
import
time
import
time
...
@@ -24,8 +25,6 @@ import asyncore
...
@@ -24,8 +25,6 @@ import asyncore
import
threading
import
threading
import
logging
import
logging
import
ThreadedAsync.LoopCallback
from
ZEO.StorageServer
import
StorageServer
from
ZEO.StorageServer
import
StorageServer
from
ZEO.runzeo
import
ZEOOptions
from
ZEO.runzeo
import
ZEOOptions
...
@@ -208,8 +207,8 @@ def main():
...
@@ -208,8 +207,8 @@ def main():
d
.
setDaemon
(
1
)
d
.
setDaemon
(
1
)
d
.
start
()
d
.
start
()
# Loop for socket events
# Loop for socket events
log
(
label
,
'entering
ThreadedAsync
loop'
)
log
(
label
,
'entering
asyncore
loop'
)
ThreadedAsync
.
LoopCallback
.
loop
()
asyncore
.
loop
()
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
...
...
src/ZEO/zrpc/connection.py
View file @
1e6c884c
...
@@ -21,7 +21,6 @@ import logging
...
@@ -21,7 +21,6 @@ import logging
import
traceback
,
time
import
traceback
,
time
import
ThreadedAsync
from
ZEO.zrpc
import
smac
from
ZEO.zrpc
import
smac
from
ZEO.zrpc.error
import
ZRPCError
,
DisconnectedError
from
ZEO.zrpc.error
import
ZRPCError
,
DisconnectedError
from
ZEO.zrpc.marshal
import
Marshaller
from
ZEO.zrpc.marshal
import
Marshaller
...
@@ -383,15 +382,7 @@ class Connection(smac.SizedMessageAsyncConnection, object):
...
@@ -383,15 +382,7 @@ class Connection(smac.SizedMessageAsyncConnection, object):
ourmap
=
{}
ourmap
=
{}
self
.
__super_init
(
sock
,
addr
,
map
=
ourmap
)
self
.
__super_init
(
sock
,
addr
,
map
=
ourmap
)
# A Connection either uses asyncore directly or relies on an
self
.
trigger
=
trigger
()
# asyncore mainloop running in a separate thread. If
# thr_async is true, then the mainloop is running in a
# separate thread. If thr_async is true, then the asyncore
# trigger (self.trigger) is used to notify that thread of
# activity on the current thread.
self
.
thr_async
=
False
self
.
trigger
=
None
self
.
_prepare_async
()
# The singleton dict is used in synchronous mode when a method
# The singleton dict is used in synchronous mode when a method
# needs to call into asyncore to try to force some I/O to occur.
# needs to call into asyncore to try to force some I/O to occur.
...
@@ -684,10 +675,7 @@ class Connection(smac.SizedMessageAsyncConnection, object):
...
@@ -684,10 +675,7 @@ class Connection(smac.SizedMessageAsyncConnection, object):
if
self
.
closed
:
if
self
.
closed
:
raise
DisconnectedError
()
raise
DisconnectedError
()
msgid
=
self
.
send_call
(
method
,
args
,
0
)
msgid
=
self
.
send_call
(
method
,
args
,
0
)
if
self
.
is_async
():
self
.
trigger
.
pull_trigger
()
self
.
trigger
.
pull_trigger
()
else
:
asyncore
.
poll
(
0.01
,
self
.
_singleton
)
return
msgid
return
msgid
def
_deferred_wait
(
self
,
msgid
):
def
_deferred_wait
(
self
,
msgid
):
...
@@ -728,23 +716,6 @@ class Connection(smac.SizedMessageAsyncConnection, object):
...
@@ -728,23 +716,6 @@ class Connection(smac.SizedMessageAsyncConnection, object):
# handle IO, possibly in async mode
# handle IO, possibly in async mode
def
_prepare_async
(
self
):
self
.
thr_async
=
False
ThreadedAsync
.
register_loop_callback
(
self
.
set_async
)
# TODO: If we are not in async mode, this will cause dead
# Connections to be leaked.
def
set_async
(
self
,
map
):
self
.
trigger
=
trigger
()
self
.
thr_async
=
True
def
is_async
(
self
):
# Overridden by ManagedConnection
if
self
.
thr_async
:
return
1
else
:
return
0
def
_pull_trigger
(
self
,
tryagain
=
10
):
def
_pull_trigger
(
self
,
tryagain
=
10
):
try
:
try
:
self
.
trigger
.
pull_trigger
()
self
.
trigger
.
pull_trigger
()
...
@@ -757,9 +728,8 @@ class Connection(smac.SizedMessageAsyncConnection, object):
...
@@ -757,9 +728,8 @@ class Connection(smac.SizedMessageAsyncConnection, object):
def
wait
(
self
,
msgid
):
def
wait
(
self
,
msgid
):
"""Invoke asyncore mainloop and wait for reply."""
"""Invoke asyncore mainloop and wait for reply."""
if
__debug__
:
if
__debug__
:
self
.
log
(
"wait(%d), async=%d"
%
(
msgid
,
self
.
is_async
()),
self
.
log
(
"wait(%d)"
%
msgid
,
level
=
TRACE
)
level
=
TRACE
)
if
self
.
is_async
():
self
.
_pull_trigger
()
self
.
_pull_trigger
()
# Delay used when we call asyncore.poll() directly.
# Delay used when we call asyncore.poll() directly.
...
@@ -778,7 +748,6 @@ class Connection(smac.SizedMessageAsyncConnection, object):
...
@@ -778,7 +748,6 @@ class Connection(smac.SizedMessageAsyncConnection, object):
self
.
log
(
"wait(%d): reply=%s"
%
self
.
log
(
"wait(%d): reply=%s"
%
(
msgid
,
short_repr
(
reply
)),
level
=
TRACE
)
(
msgid
,
short_repr
(
reply
)),
level
=
TRACE
)
return
reply
return
reply
assert
self
.
is_async
()
# XXX we're such cowards
self
.
replies_cond
.
wait
()
self
.
replies_cond
.
wait
()
finally
:
finally
:
self
.
replies_cond
.
release
()
self
.
replies_cond
.
release
()
...
@@ -793,64 +762,8 @@ class Connection(smac.SizedMessageAsyncConnection, object):
...
@@ -793,64 +762,8 @@ class Connection(smac.SizedMessageAsyncConnection, object):
def
poll
(
self
):
def
poll
(
self
):
"""Invoke asyncore mainloop to get pending message out."""
"""Invoke asyncore mainloop to get pending message out."""
if
__debug__
:
if
__debug__
:
self
.
log
(
"poll(), async=%d"
%
self
.
is_async
(),
level
=
TRACE
)
self
.
log
(
"poll()"
,
level
=
TRACE
)
if
self
.
is_async
():
self
.
_pull_trigger
()
self
.
_pull_trigger
()
else
:
asyncore
.
poll
(
0.0
,
self
.
_singleton
)
def
_pending
(
self
,
timeout
=
0
):
"""Invoke mainloop until any pending messages are handled."""
if
__debug__
:
self
.
log
(
"pending(), async=%d"
%
self
.
is_async
(),
level
=
TRACE
)
if
self
.
is_async
():
return
# Inline the asyncore poll() function to know whether any input
# was actually read. Repeat until no input is ready.
# Pending does reads and writes. In the case of server
# startup, we may need to write out zeoVerify() messages.
# Always check for read status, but don't check for write status
# only there is output to do. Only continue in this loop as
# long as there is data to read.
r
=
r_in
=
[
self
.
_fileno
]
x_in
=
[]
while
r
and
not
self
.
closed
:
if
self
.
writable
():
w_in
=
[
self
.
_fileno
]
else
:
w_in
=
[]
try
:
r
,
w
,
x
=
select
.
select
(
r_in
,
w_in
,
x_in
,
timeout
)
except
select
.
error
,
err
:
if
err
[
0
]
==
errno
.
EINTR
:
timeout
=
0
continue
else
:
raise
else
:
# Make sure any subsequent select does not block. The
# loop is only intended to make sure all incoming data is
# returned.
# Insecurity: What if the server sends a lot of
# invalidations, such that pending never finishes? Seems
# unlikely, but possible.
timeout
=
0
if
r
:
try
:
self
.
handle_read_event
()
except
asyncore
.
ExitNow
:
raise
except
:
self
.
handle_error
()
if
w
:
try
:
self
.
handle_write_event
()
except
asyncore
.
ExitNow
:
raise
except
:
self
.
handle_error
()
class
ManagedServerConnection
(
Connection
):
class
ManagedServerConnection
(
Connection
):
"""Server-side Connection subclass."""
"""Server-side Connection subclass."""
...
@@ -895,7 +808,6 @@ class ManagedClientConnection(Connection):
...
@@ -895,7 +808,6 @@ class ManagedClientConnection(Connection):
self
.
queued_messages
=
[]
self
.
queued_messages
=
[]
self
.
__super_init
(
sock
,
addr
,
obj
,
tag
=
'C'
,
map
=
client_map
)
self
.
__super_init
(
sock
,
addr
,
obj
,
tag
=
'C'
,
map
=
client_map
)
self
.
thr_async
=
True
self
.
trigger
=
client_trigger
self
.
trigger
=
client_trigger
client_trigger
.
pull_trigger
()
client_trigger
.
pull_trigger
()
...
@@ -951,16 +863,6 @@ class ManagedClientConnection(Connection):
...
@@ -951,16 +863,6 @@ class ManagedClientConnection(Connection):
# we're closed.
# we're closed.
self
.
trigger
.
pull_trigger
()
self
.
trigger
.
pull_trigger
()
def
set_async
(
self
,
map
):
pass
def
_prepare_async
(
self
):
# Don't do the register_loop_callback that the superclass does
pass
def
is_async
(
self
):
return
True
def
close
(
self
):
def
close
(
self
):
self
.
mgr
.
close_conn
(
self
)
self
.
mgr
.
close_conn
(
self
)
self
.
__super_close
()
self
.
__super_close
()
src/ZEO/zrpc/server.py
View file @
1e6c884c
...
@@ -18,10 +18,9 @@ import types
...
@@ -18,10 +18,9 @@ import types
from
ZEO.zrpc.connection
import
Connection
from
ZEO.zrpc.connection
import
Connection
from
ZEO.zrpc.log
import
log
from
ZEO.zrpc.log
import
log
import
logging
import
logging
import
ThreadedAsync.LoopCallback
# Export the main asyncore loop
# Export the main asyncore loop
loop
=
ThreadedAsync
.
LoopCallback
.
loop
loop
=
asyncore
.
loop
class
Dispatcher
(
asyncore
.
dispatcher
):
class
Dispatcher
(
asyncore
.
dispatcher
):
"""A server that accepts incoming RPC connections"""
"""A server that accepts incoming RPC connections"""
...
...
src/ZODB/scripts/zodbload.py
View file @
1e6c884c
...
@@ -790,9 +790,6 @@ def main(args=None):
...
@@ -790,9 +790,6 @@ def main(args=None):
import
Zope2
import
Zope2
Zope2
.
startup
()
Zope2
.
startup
()
#from ThreadedAsync.LoopCallback import loop
#threading.Thread(target=loop, args=(), name='asyncore').start()
jobs
=
JobProducer
()
jobs
=
JobProducer
()
for
job
,
kw
,
frequency
,
sleep
,
repeatp
in
jobdefs
:
for
job
,
kw
,
frequency
,
sleep
,
repeatp
in
jobdefs
:
Job
=
globals
()[
job
.
capitalize
()
+
'Job'
]
Job
=
globals
()[
job
.
capitalize
()
+
'Job'
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment