# Copyright 2012 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
#       copyright notice, this list of conditions and the following
#       disclaimer in the documentation and/or other materials provided
#       with the distribution.
#     * Neither the name of Google Inc. nor the names of its
#       contributors may be used to endorse or promote products derived
#       from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


import os
import shelve
import threading


class PerfDataEntry(object):
  def __init__(self):
    self.avg = 0.0
    self.count = 0

  def AddResult(self, result):
    kLearnRateLimiter = 99  # Greater value means slower learning.
    # We use an approximation of the average of the last 100 results here:
    # The existing average is weighted with kLearnRateLimiter (or less
    # if there are fewer data points).
    effective_count = min(self.count, kLearnRateLimiter)
    self.avg = self.avg * effective_count + result
    self.count = effective_count + 1
    self.avg /= self.count


class PerfDataStore(object):
  def __init__(self, datadir, arch, mode):
    filename = os.path.join(datadir, "%s.%s.perfdata" % (arch, mode))
    self.database = shelve.open(filename, protocol=2)
    self.closed = False
    self.lock = threading.Lock()

  def __del__(self):
    self.close()

  def close(self):
    if self.closed: return
    self.database.close()
    self.closed = True

  def FetchPerfData(self, test):
    """Returns the observed duration for |test| as read from the store."""
    key = test.get_id()
    if key in self.database:
      return self.database[key].avg
    return None

  def UpdatePerfData(self, test, duration):
    """Updates the persisted value in the store with duration."""
    testkey = test.get_id()
    self.RawUpdatePerfData(testkey, duration)

  def RawUpdatePerfData(self, testkey, duration):
    with self.lock:
      if testkey in self.database:
        entry = self.database[testkey]
      else:
        entry = PerfDataEntry()
      entry.AddResult(duration)
      self.database[testkey] = entry


class PerfDataManager(object):
  def __init__(self, datadir):
    self.datadir = os.path.abspath(datadir)
    if not os.path.exists(self.datadir):
      os.makedirs(self.datadir)
    self.stores = {}  # Keyed by arch, then mode.
    self.closed = False
    self.lock = threading.Lock()

  def __del__(self):
    self.close()

  def close(self):
    if self.closed: return
    for arch in self.stores:
      modes = self.stores[arch]
      for mode in modes:
        store = modes[mode]
        store.close()
    self.closed = True

  def GetStore(self, arch, mode):
    with self.lock:
      if not arch in self.stores:
        self.stores[arch] = {}
      modes = self.stores[arch]
      if not mode in modes:
        modes[mode] = PerfDataStore(self.datadir, arch, mode)
      return modes[mode]


class NullPerfDataStore(object):
  def UpdatePerfData(self, test, duration):
    pass

  def FetchPerfData(self, test):
    return None


class NullPerfDataManager(object):
  def __init__(self):
    pass

  def GetStore(self, *args, **kwargs):
    return NullPerfDataStore()

  def close(self):
    pass


def GetPerfDataManager(context, datadir):
  if context.use_perf_data:
    return PerfDataManager(datadir)
  else:
    return NullPerfDataManager()
