summaryrefslogtreecommitdiffstats
path: root/nova/db
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/db
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/db')
-rw-r--r--nova/db/sqlalchemy/session.py15
1 files changed, 14 insertions, 1 deletions
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)