/* Caching of GDB/DWARF index files.

   Copyright (C) 2018-2019 Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifndef DWARF_INDEX_CACHE_H
#define DWARF_INDEX_CACHE_H

#include "dwarf-index-common.h"
#include "common/array-view.h"
#include "symfile.h"

/* Base of the classes used to hold the resources of the indices loaded from
   the cache (e.g. mmapped files).  */

struct index_cache_resource
{
  virtual ~index_cache_resource () = 0;
};

/* Class to manage the access to the DWARF index cache.  */

class index_cache
{
public:
  /* Change the directory used to save/load index files.  */
  void set_directory (std::string dir);

  /* Return true if the usage of the cache is enabled.  */
  bool enabled () const
  {
    return m_enabled;
  }

  /* Enable the cache.  */
  void enable ();

  /* Disable the cache.  */
  void disable ();

  /* Store an index for the specified object file in the cache.  */
  void store (struct dwarf2_per_objfile *dwarf2_per_objfile);

  /* Look for an index file matching BUILD_ID.  If found, return the contents
     as an array_view and store the underlying resources (allocated memory,
     mapped file, etc) in RESOURCE.  The returned array_view is valid as long
     as RESOURCE is not destroyed.

     If no matching index file is found, return an empty array view.  */
  gdb::array_view<const gdb_byte>
  lookup_gdb_index (const bfd_build_id *build_id,
		    std::unique_ptr<index_cache_resource> *resource);

  /* Return the number of cache hits.  */
  unsigned int n_hits () const
  { return m_n_hits; }

  /* Record a cache hit.  */
  void hit ()
  {
    if (enabled ())
      m_n_hits++;
  }

  /* Return the number of cache misses.  */
  unsigned int n_misses () const
  { return m_n_misses; }

  /* Record a cache miss.  */
  void miss ()
  {
    if (enabled ())
      m_n_misses++;
  }

private:

  /* Compute the absolute filename where the index of the objfile with build
     id BUILD_ID will be stored.  SUFFIX is appended at the end of the
     filename.  */
  std::string make_index_filename (const bfd_build_id *build_id,
				   const char *suffix) const;

  /* The base directory where we are storing and looking up index files.  */
  std::string m_dir;

  /* Whether the cache is enabled.  */
  bool m_enabled = false;

  /* Number of cache hits and misses during this GDB session.  */
  unsigned int m_n_hits = 0;
  unsigned int m_n_misses = 0;
};

/* The global instance of the index cache.  */
extern index_cache global_index_cache;

#endif /* DWARF_INDEX_CACHE_H */
