Remove mysql and oracle resources for anna-ericsson project
[anna.git] / source / dbos / StorageArea.cpp
diff --git a/source/dbos/StorageArea.cpp b/source/dbos/StorageArea.cpp
deleted file mode 100644 (file)
index 830f647..0000000
+++ /dev/null
@@ -1,1081 +0,0 @@
-// ANNA - Anna is Not Nothingness Anymore                                                         //
-//                                                                                                //
-// (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
-//                                                                                                //
-// See project site at http://redmine.teslayout.com/projects/anna-suite                           //
-// See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
-
-
-#include <typeinfo>
-
-#include <algorithm>
-
-#include <anna/core/tracing/Logger.hpp>
-#include <anna/core/functions.hpp>
-
-#include <anna/dbms/dbms.hpp>
-#include <anna/dbos/dbos.hpp>
-
-#include <anna/xml/Node.hpp>
-#include <anna/xml/Attribute.hpp>
-
-using namespace std;
-using namespace anna;
-
-StorageArea::StorageArea(const char* name, const Size maxSize, ObjectAllocator objectAllocator, const StorageArea::AccessMode::_v accessMode, const int errorCode) :
-  a_name(name),
-  a_maxSize(maxSize),
-  a_objectAllocator(objectAllocator),
-  a_accessMode(accessMode),
-  a_errorCode(errorCode),
-  a_indexBlock(0),
-  a_sizeof(0),
-  a_doneReuse(0) {
-  a_blocks.push_back(a_currentBlock = new Block(objectAllocator, maxSize));
-  a_hit = a_fault = 0;
-}
-
-StorageArea::~StorageArea() {
-}
-
-//------------------------------------------------------------------------------------------------
-// Carga los datos del objeto y los guarda en el area de almacemiento.
-//
-// (1) Si no esta en memoria => se carga.
-//     (1.1) Si el registro no existe => se progresa la posible excepcion.
-//
-// (2) Cambia la politica de refresco de las areas de almacenamiento ReadWrite/Dirty. La carga solo se
-// realizara cuando la copia de utilizacion sea 0. Ademas de la mejora de rendimiento aseguramos que
-// la estabilidad de una instancia se mantiene durante toda la vida de esta. Por ejmplo evitamos que
-// una instancia A este trabajando con una copia de una instancia que estamos liberando y volviendo
-// a cargar con datos totalmente distintos ... imaginad que estamos recorriendo un vector asociado
-// o algo asi.
-//
-// (3) Si no ha podido ser recargada (seguramente tiene mas de una referencia) debe evitar el
-// uso en caso de que este marcada como Dirty.
-// (4) Si el contador de uso es cero => que ya esta marcado como memoria libre, pero recordar que
-// tambien puede estar en la memoria activa (pendiente de liberar y/o volver a usar). En este
-// caso se ha reusado.
-//------------------------------------------------------------------------------------------------
-Object* StorageArea::instance(Connection* connection, Loader& loader)
-throw(RuntimeException, DatabaseException) {
-  const Index index = loader.getIndex();
-  Object* result(NULL);
-  Instance* instance(NULL);
-  LOGDEBUG(
-    string msg("Instantiate (init) | ");
-    msg += asString();
-    msg += " | ";
-    msg += loader.asString();
-    msg += " | Index: ";
-    msg += functions::asHexString(index);
-    Logger::write(Logger::Debug, msg, ANNA_FILE_LOCATION)
-  );
-  loader.a_connection = connection;
-  std::string name("dbos::StorageArea::instance with ");
-  name += typeid(loader).name();
-  Guard guard(this, name.c_str());
-  iterator ii = a_directory.find(index);
-
-  if(ii == a_directory.end()) {                                                 // (1)
-    a_fault ++;
-
-    if(loader.load(connection, this) == true) {                                     // (1.1)
-      pair <iterator, bool> rr;
-      bool wasInserted = false;
-      instance = allocate();
-
-      try {
-        instance->object->setIndex(index);
-        /* Al añadir la instancia antes de invocar al método Object::initialize
-         * nos aseguramos de que se permitan implementar relaciones circulares
-         */
-        rr = a_directory.insert(value_type(index, instance));
-        wasInserted = true;
-        result = instance->object;
-        instance->flags |= Flag::InProgress;
-        instance->object->initialize(loader);
-        instance->object->a_isStored = true;
-        instance->flags &= Flag::Done;
-      } catch(DatabaseException&) {
-        instance->flags &= Flag::Done;
-
-        if(wasInserted)
-          a_directory.erase(rr.first);
-
-        a_holes.insert(instance, Holes::Mode::ReadyToReuse);
-        throw;
-      } catch(RuntimeException&) {
-        instance->flags &= Flag::Done;
-
-        if(wasInserted)
-          a_directory.erase(rr.first);
-
-        a_holes.insert(instance, Holes::Mode::ReadyToReuse);
-        throw;
-      }
-    }
-  } else {
-    static const bool IgnoreDirty = true;
-    verifyStatus(instance = StorageArea::instance(ii), IgnoreDirty);
-
-    switch(a_accessMode) {
-    case AccessMode::ReadOnly:
-      result = ((instance->flags & Flag::Dirty) == 0) ? instance->object : reload(connection, loader, instance);
-      break;
-    case AccessMode::ReadWrite:
-      result = (instance->copyCounter > 0) ? instance->object : reload(connection, loader, instance);
-      break;
-    case AccessMode::ReadEver:
-      result = reload(connection, loader, instance);
-      break;
-    }
-
-    if(instance->flags & Flag::Dirty) {                                        // (3)
-      string msg(asString());
-      msg += " | ";
-      msg += asString(instance);
-      msg += " | Instance selected as unusable";
-      throw RuntimeException(msg, ANNA_FILE_LOCATION);
-    }
-
-    if(result != NULL) {
-      a_holes.erase(instance);                                                // (4)
-      instance->copyCounter ++;
-      a_hit ++;
-    }
-  }
-
-  LOGINFORMATION(
-    string msg("Instantiate (final) | ");
-    msg += asString();
-    msg += " | ";
-    msg += asString(instance);
-    Logger::information(msg, ANNA_FILE_LOCATION)
-  );
-  return result;
-}
-
-Object* StorageArea::instance(Connection* connection, CrossedLoader& crossedLoader, Loader& loader)
-throw(RuntimeException, DatabaseException) {
-  Object* result = NULL;
-  crossedLoader.a_connection = connection;
-  // Si el seek devuelve 'true' es que ya tiene cargada la correspondencia entre la clave alternativa y la
-  // clave principal usada en el Loader recibido como parámetro.
-  bool loaded = (crossedLoader.seek() == false) ? crossedLoader.load(connection, this) : true;
-
-  if(loaded == true) {
-    /*
-     * Transfiere la clave principal conseguida por el cargador cruzado.
-     */
-    loader.upload(crossedLoader);
-    result = instance(connection, loader);
-    /*
-     * Da la posibilidad de que el cargador cruzado mantenga la correspondencia entre sus claves y las claves primarias
-     */
-    crossedLoader.download(loader);
-  }
-
-  return result;
-}
-
-//-------------------------------------------------------------------------
-// Crea un nuevo objeto en el area de almacenamiento.
-//-------------------------------------------------------------------------
-Object* StorageArea::create(Connection* connection, Creator& creator)
-throw(RuntimeException, DatabaseException) {
-  const Index index = creator.getIndex();
-  Instance* instance = NULL;
-  Object* result = NULL;
-
-  if(a_accessMode == AccessMode::ReadOnly) {
-    string msg(asString());
-    msg += " | Cannot create object with AccessMode::ReadOnly";
-    throw RuntimeException(msg, ANNA_FILE_LOCATION);
-  }
-
-  LOGDEBUG(
-    string msg(asString());
-    msg += " | ";
-    msg += creator.asString();
-    msg += " | Index: ";
-    msg += functions::asHexString(index);
-    Logger::write(Logger::Debug, msg, ANNA_FILE_LOCATION)
-  );
-  creator.a_connection = connection;
-  std::string name("dbos::StorageArea::create with ");
-  name += typeid(creator).name();
-  Guard guard(this, name.c_str());
-  iterator ii = a_directory.find(index);
-
-  if(ii == a_directory.end()) {
-    pair <iterator, bool> rr;
-    bool wasInserted = false;
-    a_fault ++;
-    instance = allocate();
-
-    try {
-      instance->object->setIndex(index);
-      instance->copyCounter = 1;
-      result = instance->object;
-      rr = a_directory.insert(value_type(index, instance));
-      wasInserted = true;
-      instance->flags |= Flag::InProgress;
-      instance->object->create(creator);
-      instance->flags &= Flag::Done;
-      instance->object->a_isStored = false;
-    } catch(DatabaseException&) {
-      instance->flags &= Flag::Done;
-
-      if(wasInserted)
-        a_directory.erase(rr.first);
-
-      a_holes.insert(instance, Holes::Mode::ReadyToReuse);
-      throw;
-    } catch(RuntimeException&) {
-      instance->flags &= Flag::Done;
-
-      if(wasInserted)
-        a_directory.erase(rr.first);
-
-      a_holes.insert(instance, Holes::Mode::ReadyToReuse);
-      throw;
-    }
-  } else {
-    verifyStatus(instance = StorageArea::instance(ii));
-    a_hit ++;
-    a_holes.erase(instance);
-    instance->copyCounter ++;
-    result = instance->object;
-  }
-
-  LOGINFORMATION(
-    string msg("Create | ");
-    msg += asString();
-    msg += " | ";
-    msg += asString(instance);
-    Logger::information(msg, ANNA_FILE_LOCATION)
-  );
-  return result;
-}
-
-//-------------------------------------------------------------------------
-// Carga los datos del objeto y los guarda en el area de almacemiento.
-//
-// (1) Si tiene cuenta 0 => estaba en la lista de objetos liberados =>
-//     lo sacamos de ah�
-//-------------------------------------------------------------------------
-Object* StorageArea::find(Loader& loader)
-throw(RuntimeException) {
-  const Index index = loader.getIndex();
-  Instance* instance = NULL;
-  Object* result = NULL;
-  LOGDEBUG(
-    string msg(asString());
-    msg += " | ";
-    msg += loader.asString();
-    msg += " | Index: ";
-    msg += functions::asHexString(index);
-    Logger::write(Logger::Debug, msg, ANNA_FILE_LOCATION)
-  );
-  std::string name("dbos::StorageArea::find with ");
-  name += typeid(loader).name();
-  Guard guard(this, name.c_str());
-  iterator ii = a_directory.find(index);
-
-  if(ii != a_directory.end()) {
-    verifyStatus(instance = StorageArea::instance(ii));
-    a_hit ++;
-    a_holes.erase(instance);
-    instance->copyCounter ++;
-    result = instance->object;
-  } else
-    a_fault ++;
-
-  LOGDEBUG(
-    string msg("Find | ");
-    msg += asString();
-    msg += " | ";
-    msg += asString(instance);
-    Logger::write(Logger::Debug, msg, ANNA_FILE_LOCATION)
-  );
-  return result;
-}
-
-Object* StorageArea::duplicate(const Object* object)
-throw(RuntimeException) {
-  if(object == NULL) return NULL;
-
-  std::string name("dbos::StorageArea::duplicate with ");
-  name += typeid(*object).name();
-  Guard guard(this, name.c_str());
-  iterator ii = a_directory.find(object->getIndex());
-
-  if(ii == a_directory.end()) {
-    a_fault ++;
-    string msg(asString());
-    msg += " | Index: ";
-    msg += functions::asHexString(object->getIndex());
-    msg += " | Invalid instance";
-    throw RuntimeException(msg, ANNA_FILE_LOCATION);
-  }
-
-  Instance* instance = NULL;
-  verifyStatus(instance = StorageArea::instance(ii));
-  a_holes.erase(instance);
-  instance->copyCounter ++;
-  a_hit ++;
-  LOGINFORMATION(
-    string msg("Duplicate | ");
-    msg += asString();
-    msg += " | ";
-    msg += asString(instance);
-    Logger::information(msg, ANNA_FILE_LOCATION)
-  );
-  return instance->object;
-}
-
-bool StorageArea::isLoaded(const Loader& loader)
-throw(RuntimeException) {
-  const Index index = loader.getIndex();
-  std::string name("dbos::StorageArea::isLoaded with ");
-  name += typeid(loader).name();
-  Guard guard(this, name.c_str());
-  iterator ii = a_directory.find(index);
-  const bool result = (ii != a_directory.end());
-  LOGDEBUG(
-    string msg(asString());
-    msg += " | ";
-    msg += loader.asString();
-    msg += " | Index: ";
-    msg += functions::asHexString((int) index);
-    msg += functions::asText(" | isLoaded: ", result);
-    Logger::debug(msg, ANNA_FILE_LOCATION);
-  );
-  return result;
-}
-
-void StorageArea::apply(Connection& connection, Recorder& recorder)
-throw(RuntimeException, DatabaseException) {
-  ResultCode resultCode = connection.execute(recorder.getStatement());
-
-  if(resultCode.successful() == false)
-    throw DatabaseException(resultCode, ANNA_FILE_LOCATION);
-}
-
-//------------------------------------------------------------------------------------------------
-// Borra un objeto del medio fisico => lo borra tambien de la cache
-//
-// (1) Como copyCounter = 0 => Lo metera en lista de huecos, le quitara del directorio y
-// si fuera necesario invocara al 'destroy'.
-// (2) No la puede sacar de la memoria porque tiene referencias activas, pero por lo menos la
-// marca como no usable para intentar provocar los avisos de uso incorrecto y expulsar la
-// instancia en cuanto pueda.
-//------------------------------------------------------------------------------------------------
-void StorageArea::apply(Connection& connection, Eraser& eraser)
-throw(RuntimeException, DatabaseException) {
-  if(a_accessMode == AccessMode::ReadOnly) {
-    string msg(asString());
-    msg += " | Cannot erase object with AccessMode::ReadOnly";
-    throw RuntimeException(msg, ANNA_FILE_LOCATION);
-  }
-
-  Object* object = eraser.getObject();
-  eraser.a_connection = &connection;
-  std::string name("dbos::StorageArea::apply with ");
-  name += typeid(eraser).name();
-  Guard guard(this, name.c_str());
-  Instance* instance = NULL;
-
-  if(object != NULL) {
-    iterator ii = a_directory.find(object->getIndex());
-
-    if(ii != a_directory.end()) {
-      instance = StorageArea::instance(ii);
-
-      if(instance->copyCounter > 1) {
-        instance->flags |= Flag::Incoherent;                         // (2)
-        string msg(eraser.asString());
-        msg += " | Instances: ";
-        msg += functions::asString(instance->copyCounter);
-        msg += " | Cannot delete object";
-        throw RuntimeException(msg, ANNA_FILE_LOCATION);
-      }
-    }
-  }
-
-  ResultCode resultCode = connection.execute(eraser.getStatement());
-
-  if(resultCode.successful() == false)
-    throw DatabaseException(resultCode, ANNA_FILE_LOCATION);
-
-  if(instance != NULL) {
-    instance->copyCounter = 0;
-    quickReusing(instance);                                             // (1)
-  }
-}
-
-//------------------------------------------------------------------------------------------------
-// Decrementa la cuenta de utilizacin del objeto recibido como parametro.
-//
-// (1) Si la instancia que estamos liberando esta marcada como 'Incoherente' y es la ultima
-// referencia => es el momento de expulsarla de la memoria.
-// (2) Queda a la espera de que se vuelva a usar la referencia o que el numero de registros en
-// memoria alcance un numero tal que implique comenzar a reusar objetos liberados.
-//------------------------------------------------------------------------------------------------
-void StorageArea::release(Object** object)
-throw(RuntimeException) {
-  if(object == NULL) return;
-
-  if(*object == NULL) return;
-
-  std::string name("dbos::StorageArea::release with ");
-  name += typeid(**object).name();
-  Guard guard(this, name.c_str());
-  iterator ii = a_directory.find((*object)->getIndex());
-
-  if(ii == a_directory.end())
-    return;
-
-  Instance* instance = StorageArea::instance(ii);
-
-  if(instance->copyCounter > 0) {
-    if(-- instance->copyCounter == 0) {
-      if(instance->flags & Flag::Incoherent)                                   // (1)
-        quickReusing(instance);
-      else
-        a_holes.insert(instance, Holes::Mode::TimeWait);                     // (2)
-    }
-  }
-
-  LOGINFORMATION(
-    string msg("Release | ");
-    msg += asString();
-    msg += " | ";
-    msg += asString(instance);
-    Logger::information(msg, ANNA_FILE_LOCATION)
-  );
-  *object = NULL;
-}
-
-//------------------------------------------------------------------------------------------------
-// Elimina toda la informacin referente al objeto recibido como parametro.
-//
-// (1) No la puede sacar de la memoria porque tiene referencias activas, pero por lo menos la
-// marca como no usable para intentar provocar los avisos de uso incorrecto y expulsar la
-// instancia en cuanto pueda.
-// (2) Como copyCounter = 0 => Lo metera en lista de huecos, le quitara del directorio y
-// si fuera necesario invocara al 'destroy'.
-//------------------------------------------------------------------------------------------------
-void StorageArea::erase(Object** object)
-throw(RuntimeException) {
-  if(object == NULL) return;
-
-  if(*object == NULL) return;
-
-  std::string name("dbos::StorageArea::erase with ");
-  name += typeid(**object).name();
-  Guard guard(this, name.c_str());
-  iterator ii = a_directory.find((*object)->getIndex());
-
-  if(ii == a_directory.end())
-    return;
-
-  Instance* instance = StorageArea::instance(ii);
-
-  if(instance->copyCounter > 1) {
-    instance->flags |= Flag::Incoherent;                                 // (1)
-    string msg(asString());
-    msg += " | ";
-    msg += asString(instance);
-    msg += " | Cannot dump instance";
-    throw RuntimeException(msg, ANNA_FILE_LOCATION);
-  }
-
-  LOGDEBUG(
-    string msg("Erase | ");
-    msg += asString();
-    msg += " | ";
-    msg += asString(instance);
-    Logger::debug(msg, ANNA_FILE_LOCATION)
-  );
-  instance->copyCounter = 0;
-  quickReusing(instance);                                                 // (2)
-  *object = NULL;
-}
-
-void StorageArea::dirty(Object* object)
-throw(RuntimeException) {
-  if(object == NULL) return;
-
-  std::string name("dbos::StorageArea::dirty with ");
-  name += typeid(*object).name();
-  Guard guard(this, name.c_str());
-  iterator ii = a_directory.find(object->getIndex());
-
-  if(ii == a_directory.end())
-    return;
-
-  Instance* instance = StorageArea::instance(ii);
-
-  if(instance->copyCounter > 1 && Logger::isActive(Logger::Warning)) {
-    string msg(asString());
-    msg += " | ";
-    msg += asString(instance);
-    msg += " | More than one copy on instance to be selected";
-    Logger::warning(msg, ANNA_FILE_LOCATION);
-  }
-
-  LOGDEBUG(
-    string msg("Dirty | ");
-    msg += asString();
-    msg += " | ";
-    msg += asString(instance);
-    Logger::debug(msg, ANNA_FILE_LOCATION)
-  );
-}
-
-//--------------------------------------------------------------------------------------------
-// Descarga todos los objetos de este area de almacenamiento.
-//
-// (1) Para que permite incluirla en los huecos.
-// (3) Si fuera necesario invoca al destroy => cuando se reuse no tendra que hacerlo.
-// (4) Si la entrada estaba marcada como 'incoherente' la desmarca, ya que hemos conseguido
-// expulsarla de cache.
-//--------------------------------------------------------------------------------------------
-void StorageArea::clear()
-throw(RuntimeException) {
-  Guard guard(this, "dbos::StorageArea::clear");
-  Instance* instance;
-  int n = 0;
-
-  for(iterator ii = begin(), maxii = end(); ii != maxii; ii ++) {
-    instance = StorageArea::instance(ii);
-    instance->copyCounter = 0;                                              // (1)
-    a_holes.insert(instance, Holes::Mode::ReadyToReuse);
-
-    if((instance->flags & Flag::Empty) == 0) {                              // (3)
-      LOGINFORMATION(
-        string msg("Destroy (clear) | ");
-        msg += asString();
-        msg += " | ";
-        msg += asString(instance);
-        Logger::information(msg, ANNA_FILE_LOCATION);
-      );
-      instance->object->destroy();
-      instance->flags |= Flag::Empty;
-    }
-
-    instance->flags &= Flag::NoIncoherent;                                  // (4)
-    n ++;
-  }
-
-  a_directory.clear();
-  LOGWARNING(
-    string msg("Clear | ");
-    msg += asString();
-    msg += functions::asText(" | Destroyed objects: ", n);
-    Logger::warning(msg, ANNA_FILE_LOCATION)
-  );
-}
-
-//---------------------------------------------------------------------------------------------------
-// Intenta recargar la informacion del medio fisico en la instancia del objeto.
-// Si hay algun problema y la instancia no puede guardarse en la de objetos disponibles
-// (a_holes.insert == false) => se marca como corrupto y no se podra usar hasta que
-// que no se libere su ultima instancia.
-//
-// (1) Si hubiera algun problema al invocar al 'initialize' no habria que volver a invocar
-// a este metodo.
-// (2) Recordar que la recarga solo se intenta cuando la copyCounter = 0, por tanto en el caso de
-// intentar recargar un registro que ha sido borrado no se vuelve a grabar como Ready porque
-// YA esta en la lista de huecos y seria necesario borrarlo de esta, cambiarle el msHoleTime y
-// volverlo a grabar, pero la cosa funciona porque se saca del directorio de objetos cargados
-// y se libera su memoria.
-//---------------------------------------------------------------------------------------------------
-Object* StorageArea::reload(dbms::Connection* connection, Loader& loader, StorageArea::Instance* instance)
-throw(RuntimeException, dbms::DatabaseException) {
-  const bool enableUpdate = (instance->flags & Flag::Dirty) ? true : instance->object->enableUpdate();
-  bool hasChanges(false);
-
-  if(enableUpdate == true) {
-    try {
-      if(loader.load(connection, this) == false) {
-        checkIncoherence(instance);                                          // (2)
-        return NULL;
-      }
-    } catch(RuntimeException&) {
-      checkIncoherence(instance);
-      throw;
-    } catch(dbms::DatabaseException&) {
-      checkIncoherence(instance);
-      throw;
-    }
-
-    hasChanges = (instance->flags & Flag::Dirty) ? true : instance->object->hasChanges(loader);
-  }
-
-  LOGDEBUG(
-    string msg("Reload | ");
-    msg += asString();
-    msg += " | ";
-    msg += asString(instance);
-    msg += anna::functions::asText(" | EnableUpdate: ", enableUpdate);
-    msg += anna::functions::asText(" | HasChanges: ", hasChanges);
-    Logger::debug(msg, ANNA_FILE_LOCATION);
-  );
-
-  if(hasChanges == true) {
-    LOGINFORMATION(
-      string msg("Destroy (reload) | ");
-      msg += asString();
-      msg += " | ";
-      msg += asString(instance);
-      Logger::information(msg, ANNA_FILE_LOCATION);
-    );
-    instance->object->destroy();
-    instance->flags |= Flag::Empty;                                            // (1)
-    instance->object->initialize(loader);
-    instance->flags &= Flag::NoEmpty;
-    instance->flags &= Flag::NoDirty;
-  }
-
-  return instance->object;
-}
-
-//------------------------------------------------------------------------------------------------
-// Cuando intenta recargar la informacion de una instancia desde el medio fisico, pero el
-// registro ha sido borrado =>
-// 1.- Si hay alguna instancia en uso => no puede liberar la instancia porque algun otro
-// objeto la tiene referenciada => la marca como corrupta.
-// 2.- Si hay una unica instancia en uso => puede liberarla
-//
-// (1) si la puede grabar en los huecos o la instancia ya esta en los huecos => saca el objeto
-// del directorio porque yo no es valido. Recupera la coherencia memoria-medio_fisico
-// porque ha conseguido "expulsar" de la cache el registro borrado.
-// (2) No puede "expulsar" el registro de la cache porque hay algun otro objeto que lo esta
-// referenciando => Marca ESTA instancia como incoherente => no se podra duplicar y volver
-// a instanciar, etc, etc
-//------------------------------------------------------------------------------------------------
-void StorageArea::checkIncoherence(StorageArea::Instance* instance)
-throw() {
-  if(quickReusing(instance) == true) {
-    LOGWARNING(
-      string msg("dbos::StorageArea::checkIncoherence | ");
-      msg += asString();
-      msg += " | ";
-      msg += asString(instance);
-      msg += " | Recover coherence between physical media and memory";
-      Logger::warning(msg, ANNA_FILE_LOCATION);
-    );
-  } else {                                                             // (2)
-    instance->flags |= Flag::Incoherent;
-    LOGWARNING(
-      string msg("dbos::StorageArea::checkIncoherence | ");
-      msg += asString();
-      msg += " | ";
-      msg += asString(instance);
-      msg += " | Detected incoherence between physical media and memory";
-      Logger::warning(msg, ANNA_FILE_LOCATION);
-    );
-  }
-}
-
-//------------------------------------------------------------------------------------------------
-// (1) si la puede grabar en los huecos o la instancia ya esta en los huecos => (2)
-// (2) saca el objeto del directorio porque yo no es valido.
-// (3) Si fuera necesario invoca al destroy => cuando se reuse no tendra que hacerlo.
-// (4) Si la entrada estaba marcada como 'incoherente' la desmarca, ya que hemos conseguido
-// expulsarla de cache.
-//
-// Recordar que en el caso de intentar recargar un registro que ha sido borrado no se vuelve
-// a grabar como Ready porque ya esta en la lista de huecos y seria necesario borrarlo de
-// esta, cambiarle el msHoleTime y volverlo a grabar.
-//------------------------------------------------------------------------------------------------
-bool StorageArea::quickReusing(StorageArea::Instance* instance)
-throw() {
-  bool result(false);
-
-  if(a_holes.insert(instance, Holes::Mode::ReadyToReuse) == true) {          // (1)
-    iterator ii = a_directory.find(instance->object->getIndex());
-
-    if(ii != a_directory.end())                                             // (2)
-      a_directory.erase(ii);
-
-    if((instance->flags & Flag::Empty) == 0) {                              // (3)
-      LOGINFORMATION(
-        string msg("Destroy (quickreusing) | ");
-        msg += asString();
-        msg += " | ";
-        msg += asString(instance);
-        Logger::information(msg, ANNA_FILE_LOCATION);
-      );
-      instance->object->destroy();
-      instance->flags |= Flag::Empty;
-    }
-
-    instance->flags &= Flag::NoIncoherent;                                  // (4)
-    result = true;
-  }
-
-  return result;
-}
-
-void StorageArea::verifyStatus(StorageArea::Instance* instance, const bool ignoreDirty)
-throw(RuntimeException) {
-  if(instance->flags & Flag::Incoherent) {
-    string msg(asString());
-    msg += " | ";
-    msg += asString(instance);
-    msg += " | Physical media and memory do not match";
-    throw RuntimeException(msg, ANNA_FILE_LOCATION);
-  }
-
-  if(instance->flags & Flag::Empty) {
-    string msg(asString());
-    msg += " | ";
-    msg += asString(instance);
-    msg += " | Instance is empty";
-    throw RuntimeException(msg, ANNA_FILE_LOCATION);
-  }
-
-  if(ignoreDirty == false && (instance->flags & Flag::Dirty)) {
-    string msg(asString());
-    msg += " | ";
-    msg += asString(instance);
-    msg += " | Instance is temporary locked";
-    throw RuntimeException(msg, ANNA_FILE_LOCATION);
-  }
-
-  if(instance->flags & Flag::InProgress) {
-    string msg(asString());
-    msg += " | ";
-    msg += asString(instance);
-    msg += " | Instance already has word in progress";
-    throw RuntimeException(msg, ANNA_FILE_LOCATION);
-  }
-}
-
-string StorageArea::asString() const
-throw() {
-  string result("dbos::StorageArea { Name: ");
-  const int ratio = (a_hit == 0) ? 0 : (a_hit * 100) / (a_fault + a_hit);
-  /* Nº real de objetos en uso. En el directorio también se mantienen los que tienen la cuenta de utilización a 0 */
-  const int n = a_directory.size() - a_holes.size();
-  result += a_name;
-  result += " | N: ";
-  result += functions::asString(a_maxSize);
-  result += " | n: ";
-  result += functions::asString(n);
-  result += " | r: ";
-  result += functions::asString(a_directory.size());
-  result += " | AccessMode: ";
-  result += AccessMode::asString(a_accessMode);
-  result += " | Holes: ";
-  result += functions::asString(a_holes.size());
-  result += " | Reuse: ";
-  result += functions::asString(a_doneReuse);
-  result += " | Hit: ";
-  result += functions::asString(a_hit);
-  result += " | Fault: ";
-  result += functions::asString(a_fault);
-  result += " | Ratio: ";
-  result += functions::asString(ratio);
-  return result += "% }";
-}
-
-xml::Node* StorageArea::asXML(xml::Node* parent) const
-throw() {
-  xml::Node* result = parent->createChild("dbos.StorageArea");
-  xml::Node* node;
-  const int ratio = (a_hit == 0) ? 0 : (a_hit * 100) / (a_fault + a_hit);
-  result->createAttribute("Name", a_name);
-  result->createAttribute("AccessMode", AccessMode::asString(a_accessMode));
-  node = result->createChild("Size");
-  node->createAttribute("Value", a_directory.size() - a_holes.size());
-  node->createAttribute("Reserve", a_directory.size());
-  node->createAttribute("MaxValue", a_maxSize);
-  node->createAttribute("Holes", a_holes.size());
-  node = result->createChild("SizeOf");
-  node->createAttribute("Value", asMemorySize(getSizeOf()));
-  node->createAttribute("MaxValue", asMemorySize(getMaxSizeOf()));
-  node = result->createChild("Statistics");
-  node->createAttribute("Hit", a_hit);
-  node->createAttribute("Fault", a_fault);
-  node->createAttribute("Ratio", anna::functions::asString("%d%%", ratio));
-  node->createAttribute("DoneReuse", a_doneReuse);
-  return result;
-}
-
-string StorageArea::asMemorySize(const Size size)
-throw() {
-  string result;
-
-  if(size < 1024) {
-    result = functions::asString("%u bytes", size);
-  } else if(size < 1024 * 1024) {
-    static const Size ka = 1024;
-    result += functions::asString("%u Kb", size / ka);
-  } else {
-    static const Size mega = 1024 * 1024;
-    result += functions::asString("%u Mb", size / mega);
-  }
-
-  return result;
-}
-
-StorageArea::Instance* StorageArea::allocate()
-throw() {
-  Instance* result = NULL;
-
-  if((result = reuse()) == NULL) {
-    if((result = a_currentBlock->getInstance()) == NULL) {
-      if(++ a_indexBlock == a_blocks.size())
-        a_blocks.push_back(a_currentBlock = new Block(a_objectAllocator, a_maxSize));
-      else
-        a_currentBlock = a_blocks [a_indexBlock];
-
-      result = a_currentBlock->getInstance();
-    }
-  }
-
-  result->copyCounter = 1;
-//xxx   result->msHoleTime = 0;
-  result->flags = Flag::None;
-//xxx   result->hasHole = false;
-  return result;
-}
-
-//-----------------------------------------------------------------------------------------------------
-// Reusa un objeto que lleva demasiado tiempo sin ser utilizado.
-//
-// (0) Si el tiempo que lleva en la lista de objetos liberados es cero => Podemos usar el re-usado
-// rapido; ya ha sido eliminado del directorio, invoca al destroy, etc, etc.
-//     (0.1) Para asegurar que NO desborde los 32 bits.
-// (1) Cuando n -> Nmax => Talpha = now => a poco tiempo que pase sin reusar los registros, estos
-// se comienzan a resuar. Cuando n -> 0 => talpha = 0 => No se reusan registros, sino que se crearan
-// nuevos.
-// (2) Si el primero de los registros disponibles no es suficientemente antiguo => no hay huecos libres
-//-----------------------------------------------------------------------------------------------------
-StorageArea::Instance* StorageArea::reuse()
-throw() {
-  if(a_holes.empty() == true)
-    return NULL;
-
-  Instance* result = NULL;
-  Instance* front = a_holes.front();
-  bool quickReuse;
-
-  if((front->flags & Flag::Ready) == false) {
-    if(a_directory.size() >= a_maxSize) {   // El directorio contiene los que tienen cuenta 0 + los que están activos.
-      result = front;
-      iterator ii = a_directory.find(result->object->getIndex());
-
-      if(ii != a_directory.end())
-        a_directory.erase(ii);
-
-      if((result->flags & Flag::Empty) == 0) {
-        LOGINFORMATION(
-          string msg("Destroy (reuse) | ");
-          msg += asString();
-          msg += " | ";
-          msg += asString(result);
-          Logger::information(msg, ANNA_FILE_LOCATION);
-        );
-        result->object->destroy();
-        result->flags &= Flag::NoEmpty;
-      }
-    }
-
-    quickReuse = false;
-  } else {
-    // Si la entrada se cargó en los huecos como "usado rápido" se toma
-    result = front;
-    quickReuse = true;
-  }
-
-  if(result != NULL) {
-    a_doneReuse ++;
-    result->flags &= Flag::NoReady;
-    result->flags &= Flag::NoHasHole;
-    a_holes.pop_front();
-  }
-
-  LOGDEBUG(
-    string msg("dbos::StorageArea::reuse | ");
-    msg += asString();
-    msg += " | ";
-    msg += StorageArea::asString(result);
-    msg += functions::asText(" | QuickReuse: ", quickReuse);
-    Logger::debug(msg, ANNA_FILE_LOCATION);
-  );
-  return result;
-}
-
-std::string StorageArea::asString(const Instance* instance)
-throw() {
-  std::string result("Instance { ");
-
-  if(instance == NULL)
-    return result += "<null> } ";
-
-  result += "Reference: ";
-  result += functions::asHexString(anna_ptrnumber_cast(instance->object));
-  result += " | Index: ";
-  result += functions::asHexString(instance->object->getIndex());
-  result += functions::asText(" | Stored: ", instance->object->a_isStored);
-  result += " | CopyCounter: ";
-  result += functions::asString((unsigned int) instance->copyCounter);
-  result += " | Flags (";
-  result += functions::asHexString(instance->flags);
-  result += "):";
-
-  if(instance->flags == Flag::None)
-    result += " None";
-  else {
-    if(instance->flags & Flag::Dirty)
-      result += " Dirty";
-
-    if(instance->flags & Flag::Incoherent)
-      result += " Incoherent";
-
-    if(instance->flags & Flag::Empty)
-      result += " Empty";
-
-    if(instance->flags & Flag::HasHole)
-      result += " HasHole";
-
-    if(instance->flags & Flag::InProgress)
-      result += " InProgress";
-
-    result += (instance->flags & Flag::Ready) ? " Ready" : " TimeWait";
-  }
-
-  return result += " }";
-}
-
-const char* StorageArea::AccessMode::asString(const AccessMode::_v v)
-throw() {
-  static const char* text [] = { "ReadOnly", "ReadWrite", "ReadEver" };
-  return text [v];
-}
-
-/****************************************************************************************
-* Bloque de memoria.
-****************************************************************************************/
-StorageArea::Block::Block(ObjectAllocator objectAllocator, const Size maxSize) :
-  a_size(0) {
-  a_maxSize = std::min(8U, std::max(256U, maxSize >> 7));
-  a_instances = new Instance [a_maxSize];
-
-  for(int i = 0; i < a_maxSize; i ++)
-    a_instances [i].object = (*objectAllocator)();
-}
-
-bool StorageArea::Holes::insert(Instance* instance, const StorageArea::Holes::Mode::_v mode)
-throw() {
-  if(instance->copyCounter > 0)
-    return false;
-
-  /* Si la instancia ya ha sido registrada en la lista de huecos, sale sin más */
-  if((instance->flags & Flag::HasHole) == true)
-    return true;
-
-  switch(mode)  {
-  case Mode::ReadyToReuse:
-    instance->holeIterator = a_holes.insert(a_holes.begin(), instance);
-    instance->flags |= Flag::HasHole;
-    instance->flags |= Flag::Ready;
-    a_size ++;
-    break;
-  case Mode::TimeWait:
-    instance->holeIterator = a_holes.insert(a_holes.end(), instance);
-    instance->flags |= Flag::HasHole;
-    instance->flags &= Flag::NoReady;
-    a_size ++;
-    break;
-  }
-
-  LOGLOCAL6(
-    string msg("dbos::StorageArea::Holes::insert | This: ");
-    msg += functions::asHexString(anna_ptrnumber_cast(this));
-    msg += " | ";
-    msg += StorageArea::asString(instance);
-    Logger::write(Logger::Local6, msg, ANNA_FILE_LOCATION);
-  );
-  return true;
-}
-
-void StorageArea::Holes::erase(Instance* instance)
-throw() {
-  //   instance->msHoleTime = 0;
-  instance->flags |= Flag::Ready;
-
-  if(instance->copyCounter != 0)
-    return;
-
-  /* Si la instancia NO ha sido registrada en la lista de huecos, sale sin más */
-  if((instance->flags & Flag::HasHole) == false)
-    return;
-
-  LOGLOCAL6(
-    string msg("dbos::StorageArea::Holes::erase | This: ");
-    msg += functions::asHexString(anna_ptrnumber_cast(this));
-    msg += " | ";
-    msg += StorageArea::asString(instance);
-    Logger::write(Logger::Local6, msg, ANNA_FILE_LOCATION);
-  );
-  a_holes.erase(instance->holeIterator);
-  instance->flags &= Flag::NoHasHole;
-  a_size --;
-}
-
-/****************************************************************************************
-* Iterador
-
-class A {
-public:
-   A () : a (0) { cout << "C0: " << (int) this << endl; }
-   A (const int _a): a (_a) { cout << "C1: " << (int) this << " " << a << endl; }
-   A (const A& other) : a (other.a) { cout << "C2: " << (int) this << " " << a << endl; }
-
-   A& operator = (const A& other) {
-      cout << "CP: " << (int) this << " " << (a = other.a) << endl;
-      return *this;
-   }
-
-   int get () const { return a; }
-private:
-   int a;
-};
-
-A fx () { return A (2000); }
-
-int main ()
-{
-   A aa = 100;
-   A bb (200);
-   A xx = aa;
-   A cc = fx ();
-
-   cout << "CC: " << (int) &cc << " " << cc.get () << endl;
-
-}
-
-La salida del programucho es la siguiente:
-
-C1: -4198808 100
-C1: -4198812 200
-C2: -4198816 100
-C1: -4198820 2000
-CC: -4198820 2000
-
-Lo que quiere decir que la "cc" la crea directamente sobre la pila y la asigna en fx sin aplicar ningn
-otro constructor.
-
-Por eso cuando hac� StorageArea::Iterator ii = xxx->begin (), maxi = xxx->end (); .....
-no estaba pasando por el contructor copia ni por ningn otro constructor.
-
-****************************************************************************************/
-// Dejo todo el ejemplo para que sirva de recordatorio.
-