# Copyright 2017 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.

from __future__ import absolute_import
from __future__ import print_function

import logging

import common
from autotest_lib.server.hosts import host_info
from chromite.lib import metrics


_METRICS_PREFIX = 'chromeos/autotest/autoserv/host_info/shadowing_store/'
_REFRESH_METRIC_NAME = _METRICS_PREFIX + 'refresh_count'
_COMMIT_METRIC_NAME = _METRICS_PREFIX + 'commit_count'


logger = logging.getLogger(__file__)

class ShadowingStore(host_info.CachingHostInfoStore):
    """A composite CachingHostInfoStore that maintains a main and shadow store.

    ShadowingStore accepts two CachingHostInfoStore objects - primary_store and
    shadow_store. All refresh/commit operations are serviced through
    primary_store.  In addition, shadow_store is updated and compared with this
    information, leaving breadcrumbs when the two differ. Any errors in
    shadow_store operations are logged and ignored so as to not affect the user.

    This is a transitional CachingHostInfoStore that allows us to continue to
    use an AfeStore in practice, but also create a backing FileStore so that we
    can validate the use of FileStore in prod.
    """

    def __init__(self, primary_store, shadow_store,
                 mismatch_callback=None):
        """
        @param primary_store: A CachingHostInfoStore to be used as the primary
                store.
        @param shadow_store: A CachingHostInfoStore to be used to shadow the
                primary store.
        @param mismatch_callback: A callback used to notify whenever we notice a
                mismatch between primary_store and shadow_store. The signature
                of the callback must match:
                    callback(primary_info, shadow_info)
                where primary_info and shadow_info are HostInfo objects obtained
                from the two stores respectively.
                Mostly used by unittests. Actual users don't know / nor care
                that they're using a ShadowingStore.
        """
        super(ShadowingStore, self).__init__()
        self._primary_store = primary_store
        self._shadow_store = shadow_store
        self._mismatch_callback = (
                mismatch_callback if mismatch_callback is not None
                else _log_info_mismatch)
        try:
            self._shadow_store.commit(self._primary_store.get())
        except host_info.StoreError as e:
            metrics.Counter(
                    _METRICS_PREFIX + 'initialization_fail_count').increment()
            logger.exception(
                    'Failed to initialize shadow store. '
                    'Expect primary / shadow desync in the future.')

    def commit_with_substitute(self, info, primary_store=None,
                               shadow_store=None):
        """Commit host information using alternative stores.

        This is used to commit using an alternative store implementation
        to work around some issues (crbug.com/903589).

        Don't set cached_info in this function.

        @param info: A HostInfo object to set.
        @param primary_store: A CachingHostInfoStore object to commit instead of
            the original primary_store.
        @param shadow_store: A CachingHostInfoStore object to commit instead of
            the original shadow store.
        """
        if primary_store is not None:
            primary_store.commit(info)
        else:
            self._commit_to_primary_store(info)

        if shadow_store is not None:
            shadow_store.commit(info)
        else:
            self._commit_to_shadow_store(info)

    def __str__(self):
        return '%s[%s, %s]' % (type(self).__name__, self._primary_store,
                               self._shadow_store)

    def _refresh_impl(self):
        """Obtains HostInfo from the primary and compares against shadow"""
        primary_info = self._refresh_from_primary_store()
        try:
            shadow_info = self._refresh_from_shadow_store()
        except host_info.StoreError:
            logger.exception('Shadow refresh failed. '
                             'Skipping comparison with primary.')
            return primary_info
        self._verify_store_infos(primary_info, shadow_info)
        return primary_info

    def _commit_impl(self, info):
        """Commits HostInfo to both the primary and shadow store"""
        self._commit_to_primary_store(info)
        self._commit_to_shadow_store(info)

    def _commit_to_primary_store(self, info):
        try:
            self._primary_store.commit(info)
        except host_info.StoreError:
            metrics.Counter(_COMMIT_METRIC_NAME).increment(
                    fields={'file_commit_result': 'skipped'})
            raise

    def _commit_to_shadow_store(self, info):
        try:
            self._shadow_store.commit(info)
        except host_info.StoreError:
            logger.exception(
                    'shadow commit failed. '
                    'Expect primary / shadow desync in the future.')
            metrics.Counter(_COMMIT_METRIC_NAME).increment(
                    fields={'file_commit_result': 'fail'})
        else:
            metrics.Counter(_COMMIT_METRIC_NAME).increment(
                    fields={'file_commit_result': 'success'})

    def _refresh_from_primary_store(self):
        try:
            return self._primary_store.get(force_refresh=True)
        except host_info.StoreError:
            metrics.Counter(_REFRESH_METRIC_NAME).increment(
                    fields={'validation_result': 'skipped'})
            raise

    def _refresh_from_shadow_store(self):
        try:
            return self._shadow_store.get(force_refresh=True)
        except host_info.StoreError:
            metrics.Counter(_REFRESH_METRIC_NAME).increment(fields={
                    'validation_result': 'fail_shadow_store_refresh'})
            raise

    def _verify_store_infos(self, primary_info, shadow_info):
        if primary_info == shadow_info:
            metrics.Counter(_REFRESH_METRIC_NAME).increment(
                    fields={'validation_result': 'success'})
        else:
            self._mismatch_callback(primary_info, shadow_info)
            metrics.Counter(_REFRESH_METRIC_NAME).increment(
                    fields={'validation_result': 'fail_mismatch'})
            self._shadow_store.commit(primary_info)


def _log_info_mismatch(primary_info, shadow_info):
    """Log the two HostInfo instances.

    Used as the default mismatch_callback.
    """
    logger.warning('primary / shadow disagree on refresh.')
    logger.warning('primary: %s', primary_info)
    logger.warning('shadow: %s', shadow_info)
