summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorJohannes Erdfelt <johannes.erdfelt@rackspace.com>2012-09-18 23:29:41 +0000
committerJohannes Erdfelt <johannes.erdfelt@rackspace.com>2012-09-19 18:46:49 +0000
commit7df1908aae47461a648df94e7ae4bba912adee5e (patch)
treec8977ca5d44af4f9ab61090306e2442c7d29ff4a /nova
parent8473bb4cf93eb713ef42fdc87767aa938f36b43e (diff)
downloadnova-7df1908aae47461a648df94e7ae4bba912adee5e.tar.gz
nova-7df1908aae47461a648df94e7ae4bba912adee5e.tar.xz
nova-7df1908aae47461a648df94e7ae4bba912adee5e.zip
Always yield to other greenthreads after database calls
Since common database backends (eg MySQLdb and sqlite) are implemented in C extensions, eventlet cannot monkey patch the socket calls to ensure greenthread context switches occur during network I/O. Previously, this was done by sprinkling explicit greenthread.sleep(0) calls in areas known to cause problems. Switch that to always do a yield after execute. Change-Id: If91e49fbe212a02710b6ba4abd456222552e2575
Diffstat (limited to 'nova')
-rw-r--r--nova/compute/manager.py7
-rw-r--r--nova/db/sqlalchemy/session.py15
2 files changed, 14 insertions, 8 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 2f977b26c..e4db4a3c2 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -2435,9 +2435,6 @@ class ComputeManager(manager.SchedulerDependentManager):
{'status': 'error'})
for migration in migrations:
- # NOTE(comstud): Yield to other greenthreads. Putting this
- # at the top so we make sure to do it on each iteration.
- greenthread.sleep(0)
migration_id = migration['id']
instance_uuid = migration['instance_uuid']
LOG.info(_("Automatically confirming migration "
@@ -2539,8 +2536,6 @@ class ComputeManager(manager.SchedulerDependentManager):
refreshed = timeutils.utcnow()
for usage in bw_usage:
- # Allow switching of greenthreads between queries.
- greenthread.sleep(0)
self.db.bw_usage_update(context,
usage['uuid'],
usage['mac_address'],
@@ -2584,8 +2579,6 @@ class ComputeManager(manager.SchedulerDependentManager):
"%(num_vm_instances)s on the hypervisor.") % locals())
for db_instance in db_instances:
- # Allow other periodic tasks to do some work...
- greenthread.sleep(0)
db_power_state = db_instance['power_state']
if db_instance['task_state'] is not None:
LOG.info(_("During sync_power_state the instance has a "
diff --git a/nova/db/sqlalchemy/session.py b/nova/db/sqlalchemy/session.py
index 6e754be7e..6c349e0c2 100644
--- a/nova/db/sqlalchemy/session.py
+++ b/nova/db/sqlalchemy/session.py
@@ -21,6 +21,7 @@
import re
import time
+from eventlet import greenthread
from sqlalchemy.exc import DisconnectionError, OperationalError
import sqlalchemy.interfaces
import sqlalchemy.orm
@@ -66,6 +67,16 @@ def add_regexp_listener(dbapi_con, con_record):
dbapi_con.create_function('regexp', 2, regexp)
+def greenthread_yield(dbapi_con, con_record):
+ """
+ Ensure other greenthreads get a chance to execute by forcing a context
+ switch. With common database backends (eg MySQLdb and sqlite), there is
+ no implicit yield caused by network I/O since they are implemented by
+ C libraries that eventlet cannot monkey patch.
+ """
+ greenthread.sleep(0)
+
+
def ping_listener(dbapi_conn, connection_rec, connection_proxy):
"""
Ensures that MySQL connections checked out of the
@@ -122,9 +133,11 @@ def get_engine():
_ENGINE = sqlalchemy.create_engine(FLAGS.sql_connection, **engine_args)
+ sqlalchemy.event.listen(_ENGINE, 'checkin', greenthread_yield)
+
if 'mysql' in connection_dict.drivername:
sqlalchemy.event.listen(_ENGINE, 'checkout', ping_listener)
- elif "sqlite" in connection_dict.drivername:
+ elif 'sqlite' in connection_dict.drivername:
if not FLAGS.sqlite_synchronous:
sqlalchemy.event.listen(_ENGINE, 'connect',
synchronous_switch_listener)