Introduced DB pooling for non blocking DB calls

The DbApi module is wrapped with the tpool wrapper if the configuration is
enabled. use_tpool is disabled (False) by default

Related to bp mysql-thread-pool

Change-Id: Ie7274ac855549b96c581c3eb0bcf79f3c74be0ed
This commit is contained in:
sridevik 2013-08-26 05:23:34 -05:00
parent 6735fbb3f2
commit 247ada2d94
3 changed files with 88 additions and 1 deletions

View File

@ -17,6 +17,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import functools
from oslo.config import cfg
from glance.common import crypt
@ -25,13 +26,20 @@ import glance.domain
import glance.domain.proxy
from glance.openstack.common import importutils
db_opt = cfg.BoolOpt('use_tpool',
default=False,
help='Enable the use of thread pooling for '
'all DB API calls')
CONF = cfg.CONF
CONF.import_opt('metadata_encryption_key', 'glance.common.config')
CONF.register_opt(db_opt)
def get_api():
return importutils.import_module(CONF.data_api)
if not CONF.use_tpool:
return importutils.import_module(CONF.data_api)
return ThreadPoolWrapper(CONF.data_api)
# attributes common to all models
@ -260,3 +268,21 @@ class ImageMemberRepo(object):
image_member = self._format_image_member_from_db(
db_api_image_member[0])
return image_member
class ThreadPoolWrapper(object):
def __init__(self, wrapped):
self.wrapped = importutils.import_module(wrapped)
def __getattr__(self, key):
original = getattr(self.wrapped, key)
if not callable(original):
return original
@functools.wraps(original)
def wrapper(*args, **kwargs):
from eventlet import tpool
output = tpool.execute(original, *args, **kwargs)
return output
return wrapper

View File

@ -0,0 +1,60 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2013 OpenStack LLC.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from mock import Mock
from oslo.config import cfg
import testtools
from glance import db as db_api
from glance.openstack.common import importutils
CONF = cfg.CONF
CONF.import_opt('use_tpool', 'glance.db')
CONF.import_opt('data_api', 'glance.db')
class DbApiTest(testtools.TestCase):
def test_get_dbapi_when_db_pool_is_enabled(self):
CONF.set_override('use_tpool', True)
dbapi = db_api.get_api()
self.assertTrue(isinstance(dbapi, db_api.ThreadPoolWrapper))
def test_get_dbapi_when_db_pool_is_disabled(self):
CONF.set_override('use_tpool', False)
dbapi = db_api.get_api()
self.assertFalse(isinstance(dbapi, db_api.ThreadPoolWrapper))
self.assertEqual(importutils.import_module(CONF.data_api), dbapi)
def method_for_test_1(*args, **kwargs):
return args, kwargs
class ThreadPoolWrapper(testtools.TestCase):
def test_thread_pool(self):
module = importutils.import_module('glance.tests.functional.db.'
'test_db_api')
CONF.set_override('use_tpool', True)
CONF.set_override('data_api', 'glance.tests.functional.db.'
'test_db_api')
dbapi = db_api.get_api()
from eventlet import tpool
tpool.execute = Mock()
dbapi.method_for_test_1(1, 2, kwarg='arg')
tpool.execute.assert_called_with(method_for_test_1, 1, 2, kwarg='arg')

View File

@ -14,6 +14,7 @@ mox>=0.5.3
nose
nose-exclude
openstack.nose_plugin>=0.7
mock>=1.0
nosehtmloutput>=0.0.3
sphinx>=1.1.2
requests>=1.1