Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
tango
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Jira issues
Open Jira
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
LOFAR2.0
tango
Commits
5241984a
Commit
5241984a
authored
3 years ago
by
Corné Lukken
Browse files
Options
Downloads
Patches
Plain Diff
L2SS-340
: Separate condition names for different stages
parent
d594420b
No related branches found
No related tags found
1 merge request
!117
create TCPReplicator for StatisticsClient
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
devices/clients/tcp_replicator.py
+16
-8
16 additions, 8 deletions
devices/clients/tcp_replicator.py
devices/test/clients/test_tcp_replicator.py
+1
-0
1 addition, 0 deletions
devices/test/clients/test_tcp_replicator.py
with
17 additions
and
8 deletions
devices/clients/tcp_replicator.py
+
16
−
8
View file @
5241984a
...
@@ -61,8 +61,11 @@ class TCPReplicator(Thread, StatisticsClientThread):
...
@@ -61,8 +61,11 @@ class TCPReplicator(Thread, StatisticsClientThread):
self
.
initialization_semaphore
=
Semaphore
()
self
.
initialization_semaphore
=
Semaphore
()
self
.
initialization_semaphore
.
acquire
()
self
.
initialization_semaphore
.
acquire
()
# Create condition to orchestrate clean shutdown
# Create condition to orchestrate clean disconnecting and shutdown
self
.
shutdown_condition
=
Condition
()
# They are actually the same object, just with different names for
# clarity.
self
.
disconnect_condition
=
Condition
()
self
.
shutdown_condition
=
self
.
disconnect_condition
# Connected clients the event loop is managing
# Connected clients the event loop is managing
self
.
_connected_clients
=
[]
self
.
_connected_clients
=
[]
...
@@ -162,11 +165,15 @@ class TCPReplicator(Thread, StatisticsClientThread):
...
@@ -162,11 +165,15 @@ class TCPReplicator(Thread, StatisticsClientThread):
# on the main thread.
# on the main thread.
logging
.
fatal
(
"
TCPReplicator thread encountered fatal exception:
"
logging
.
fatal
(
"
TCPReplicator thread encountered fatal exception:
"
"
{}
"
.
format
(
e
))
"
{}
"
.
format
(
e
))
# We will lose the exception and the original stacktrace of the
# We will lose the exception and the original stacktrace of the
# thread. Once we use a threadpool it will be much easier to
# thread. Once we use a threadpool it will be much easier to
# retrieve this so I propose to not bother implementing it now.
# retrieve this so I propose to not bother implementing it now.
# For the pattern to do this see anyway:
# For the pattern to do this see anyway:
# https://stackoverflow.com/a/6894023
# https://stackoverflow.com/a/6894023
# Due to the exception the run method will return making is_alive()
# false
finally
:
finally
:
# Always release the lock upon error so the constructor can return
# Always release the lock upon error so the constructor can return
if
self
.
initialization_semaphore
.
acquire
(
blocking
=
False
)
is
False
:
if
self
.
initialization_semaphore
.
acquire
(
blocking
=
False
)
is
False
:
...
@@ -212,15 +219,16 @@ class TCPReplicator(Thread, StatisticsClientThread):
...
@@ -212,15 +219,16 @@ class TCPReplicator(Thread, StatisticsClientThread):
client
.
transport
.
write
(
data
)
client
.
transport
.
write
(
data
)
async
def
_disconnect
(
self
):
async
def
_disconnect
(
self
):
with
self
.
shutdown
_condition
:
with
self
.
disconnect
_condition
:
for
client
in
self
.
_connected_clients
:
for
client
in
self
.
_connected_clients
:
peername
=
client
.
transport
.
get_extra_info
(
'
peername
'
)
peername
=
client
.
transport
.
get_extra_info
(
'
peername
'
)
logger
.
debug
(
'
Disconnecting client {}
'
.
format
(
peername
))
logger
.
debug
(
'
Disconnecting client {}
'
.
format
(
peername
))
client
.
transport
.
abort
()
client
.
transport
.
abort
()
self
.
shutdown
_condition
.
notify
()
self
.
disconnect
_condition
.
notify
()
async
def
_
conditional_st
op
(
self
):
async
def
_
stop_event_lo
op
(
self
):
with
self
.
shutdown_condition
:
with
self
.
shutdown_condition
:
# Calling stop() will return control flow to self._loop.run_*()
self
.
_loop
.
stop
()
self
.
_loop
.
stop
()
@staticmethod
@staticmethod
...
@@ -245,14 +253,14 @@ class TCPReplicator(Thread, StatisticsClientThread):
...
@@ -245,14 +253,14 @@ class TCPReplicator(Thread, StatisticsClientThread):
if
not
self
.
_loop
.
is_running
():
if
not
self
.
_loop
.
is_running
():
return
return
with
self
.
shutdown
_condition
:
with
self
.
disconnect
_condition
:
self
.
_loop
.
call_soon_threadsafe
(
self
.
_loop
.
call_soon_threadsafe
(
self
.
_loop
.
create_task
,
self
.
_disconnect
())
self
.
_loop
.
create_task
,
self
.
_disconnect
())
self
.
shutdown
_condition
.
wait
()
self
.
disconnect
_condition
.
wait
()
if
self
.
_loop
.
is_running
():
if
self
.
_loop
.
is_running
():
with
self
.
shutdown_condition
:
with
self
.
shutdown_condition
:
logging
.
debug
(
"
Stopping TCPReplicator event loop
"
)
logging
.
debug
(
"
Stopping TCPReplicator event loop
"
)
self
.
_loop
.
call_soon_threadsafe
(
self
.
_loop
.
call_soon_threadsafe
(
self
.
_loop
.
create_task
,
self
.
_
conditional_st
op
())
self
.
_loop
.
create_task
,
self
.
_
stop_event_lo
op
())
self
.
shutdown_condition
.
wait
()
self
.
shutdown_condition
.
wait
()
This diff is collapsed.
Click to expand it.
devices/test/clients/test_tcp_replicator.py
+
1
−
0
View file @
5241984a
...
@@ -87,6 +87,7 @@ class TestTCPReplicator(base.TestCase):
...
@@ -87,6 +87,7 @@ class TestTCPReplicator(base.TestCase):
# Thread should now be dead
# Thread should now be dead
self
.
assertFalse
(
replicator
.
is_alive
())
self
.
assertFalse
(
replicator
.
is_alive
())
@timeout_decorator.timeout
(
5
)
def
test_start_exception
(
self
):
def
test_start_exception
(
self
):
"""
Verify the run() methods kills the thread cleanly on exceptions
"""
"""
Verify the run() methods kills the thread cleanly on exceptions
"""
m_loop
=
mock
.
Mock
()
m_loop
=
mock
.
Mock
()
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment