# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Feedback query delegate interfaces and implementation registry."""
import multiprocessing
import common
from autotest_lib.client.common_lib.feedback import client
# Mapping of query identifiers to delegate classes.
_query_delegate_registry = {}
class _QueryDelegate(object):
"""A base class for query delegates."""
_query_count = multiprocessing.Value('d', 0)
def __init__(self, test, dut, multiplexer, atomic=True):
"""Constructs the delegate.
@param test: The name of the test.
@param dut: The name of the DUT.
@param multiplexer: Feedback request multiplexer object.
@param atomic: Whether this is an atomic query.
"""
super(_QueryDelegate, self).__init__()
self.test = test
self.dut = dut
self._multiplexer = multiplexer
self._atomic = atomic
# Assign a unique query number.
with self._query_count.get_lock():
self._query_num = self._query_count.value
self._query_count.value += 1
def _process_request(self, req):
"""Submits a given request to the multiplexer for processing."""
return self._multiplexer.process_request(req, self._query_num,
self._atomic)
def prepare(self, **kwargs):
"""Delegate for a query's prepare() method."""
return self._prepare_impl(**kwargs)
def _prepare_impl(self, **kwargs):
"""Concrete implementation of the query's prepare() call."""
raise NotImplementedError
def validate(self, **kwargs):
"""Delegate for a query's validate() method.
This clears the atomic sequence with the multiplexer to make sure it
isn't blocked waiting for more requests from this query.
"""
try:
return self._validate_impl(**kwargs)
finally:
if self._atomic:
self._multiplexer.end_atomic_seq(self._query_num)
def _validate_impl(self, **kwargs):
"""Concrete implementation of the query's validate() call."""
raise NotImplementedError
class OutputQueryDelegate(_QueryDelegate):
"""A base class for output query delegates."""
class InputQueryDelegate(_QueryDelegate):
"""A base class for input query delegates."""
def emit(self):
"""Delegate for an input query's emit() method."""
return self._emit_impl()
def _emit_impl(self):
"""Concrete implementation of the query's emit() call."""
raise NotImplementedError
def register_delegate_cls(query_id, delegate_cls):
"""Registers a delegate class with a given query identifier.
@param query_id: Query identifier constant.
@param delegate_cls: The class implementing a delegate for this query.
"""
_query_delegate_registry[query_id] = delegate_cls
def get_delegate_cls(query_id):
"""Returns a query delegate class for a given query type.
@param query_id: A query type identifier.
@return A query delegate class.
@raise ValueError: Unknown query type.
@raise NotImplementedError: Query type not supported.
"""
if query_id not in client.ALL_QUERIES:
raise ValueError
if query_id not in _query_delegate_registry:
raise NotImplementedError
return _query_delegate_registry[query_id]