/******************************************************************************
* NOMAD -  Nonlinear Optimization for Mixed vAriables and Derivatives.        *
* Copyright (C) 2001-2004  Gilles Couture - Ecole Polytechnique,              *
*                          Charles Audet - Ecole Polytechnique,               *
*		           John Dennis - Rice University.                     *
*                                                                             *
* Author: Gilles Couture                                                      *
* École Polytechnique de Montréal - GERAD                                     *
* C.P. 6079, Succ. Centre-ville, Montréal (Québec) H3C 3A7 Canada             *
* Tel:  (514) 340-6053 x6928                                                  *
* Email: Gilles.Couture@gerad.ca                                              *
* Fax: (514) 340-5665                                                         *
*                                                                             *
* 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. You can find the              *
* GNU General Public License at:                                              *
*             http://www.gnu.org/copyleft/gpl.html                            *
*                                                                             *
* 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, write to the Free Software                 *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. *
*                                                                             *
* You can find information on the NOMAD software at:                          *
*             http://www.gerad.ca/NOMAD/                                      *
******************************************************************************/

// cachecontrol.cpp -- CacheControl class methods.
#include <fstream>
#include <iostream>
using namespace std;
#include "augmentedpoint.h"
#include "cachecontrol.h"
#include "database.h"
#include "defines.h"
#include "stlcache.h"

// Constructor. Two caches (BerkeleyDB objects) are created.
// The CacheControl object receives these parameters:
// - 'dim' is the problem dimension (number of variables).
// - 'out' is the number of outputs of the problem.
// - 'perm' is the path of the permanent cache.
CacheControl::CacheControl(const int dim, const int out, const char * perm)
{
  cout << "\nCreating 'CacheControl'...\n";
  display_factor = 0;
  // The caches are created here.
  perm_cache = new StlCache(perm, dim, out);
  cout << "Permanent cache created.\n";
  perm_cache->show();
  temp_cache = new StlCache(NULL, dim, out);
  cout << "Temporary cache created.\n\n";
}

// Destructor.
CacheControl::~CacheControl()
{
  cout << "\nDestroying 'CacheControl'...\n";
  // We destroy the databases.
  delete perm_cache;
  cout << "Permanent cache destroyed\n";
  delete temp_cache;
  cout << "Temporary cache destroyed.\n\n";
}

// This method checks if a point is already in one of the caches.
int CacheControl::find(AugmentedPoint & ap, const double * key) const
{
  if (temp_cache->find(ap, key) == true)
    {
      if (display_factor >= 5)
	cout << "Temporary cache hit!\n";
      return TEMP_CACHE_HIT;
    }
  else
    if (perm_cache->find(ap, key) == true)
      {
	if (display_factor >= 5)
	  cout << "Permanent cache hit!\n";
	return PERM_CACHE_HIT;
      }
    else
      return NO_CACHE_HIT;
}

// Returns the number of hits in the permanent cache.
int CacheControl::getPermCacheHits() const
{
  return perm_cache->getHits();
}

// Returns the number of hits in the temporary cache.
int CacheControl::getTempCacheHits() const
{
  return temp_cache->getHits();
}

// The run is over.
void CacheControl::closeCaches()
{
  cout << "\nThe run is over, closing caches...\n";

  cout << "Temporary cache\n---------------\n";
  temp_cache->show();

  cout << "Permanent cache\n---------------\n";
  perm_cache->show();

  // First the temporary cache is copied in the permanent cache.
  *perm_cache += *temp_cache;
  cout << "Temporary cache copied into permanent cache.\n";

  cout << "Permanent cache\n---------------\n";
  perm_cache->show();

  // The permanent cache is written to file.
  perm_cache->write();
  cout << "Permanent cache written to file.\n";
  // The temporary cache is reset.
  temp_cache->reset();
  cout << "Temporary cache erased.\n\n";

  cout << "Temporary cache\n---------------\n";
  temp_cache->show();
}

// The user wants to continue the current run.
void CacheControl::continueRun() const
{
  perm_cache->continueRun();
  temp_cache->continueRun();
}

// This method inserts a point in the caches.
void CacheControl::insert(double * inp, double * utp) const
{
  temp_cache->insert(inp, utp);
}

// show -- Outputs the CacheManager object.
void CacheControl::showOutput(ofstream & fout) const
{
  if (!fout.is_open() )
    return;
  fout << "Number of temporary cache hits: ";
  temp_cache->showOutput(fout);
  fout << "Number of permanent cache hits: ";
  perm_cache->showOutput(fout);
}
