Revert "Remove mysql and oracle resources for anna-ericsson project"
[anna.git] / include / anna / dbos / StorageArea.hpp
diff --git a/include/anna/dbos/StorageArea.hpp b/include/anna/dbos/StorageArea.hpp
new file mode 100644 (file)
index 0000000..e9bda03
--- /dev/null
@@ -0,0 +1,625 @@
+// 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 //
+
+
+#ifndef anna_dbos_StorageArea_hpp
+#define anna_dbos_StorageArea_hpp
+
+#include <vector>
+#include <map>
+#include <list>
+#include <deque>
+
+#include <algorithm>
+
+#include <anna/core/mt/Mutex.hpp>
+#include <anna/config/defines.hpp>
+#include <anna/core/util/SortedVector.hpp>
+
+#include <anna/dbms/DatabaseException.hpp>
+
+#include <anna/dbos/defines.hpp>
+#include <anna/dbos/ObjectAllocator.hpp>
+
+namespace anna {
+
+namespace xml {
+class Node;
+}
+
+namespace dbms {
+class Connection;
+}
+
+namespace dbos {
+
+class Accesor;
+class Object;
+class Creator;
+class Loader;
+class Recorder;
+class Eraser;
+class Repository;
+class CrossedLoader;
+
+/**
+   Area de almacenamiento de los objetos obtenidos a partir de los datos guardados en un medio
+   fisico, que normalmente seria una base de datos.
+
+   La creacion de cualquier área de almacenamiento debe hacerse mediante el método
+   anna::dbos::Repository::createStorageArea.
+
+   \warning Exclusivamente para uso interno de anna.dbos
+*/
+class StorageArea : public Mutex {
+  struct Instance;
+  class Block;
+  class Holes;
+
+public:
+  /**
+     Modo de acceso al área de almacenamiento.
+  */
+  struct AccessMode {
+    enum _v {
+      /**
+         Carga el objeto una vez y no lo vuelve a comprobar mientras tena un estado valido.
+         No permite la creacion de nuevos objetos.
+      */
+      ReadOnly,
+      /**
+         Carga el objeto una vez e intenta recargarlo cada vez que su cuenta de utilizacion
+         sea cero. Se invocara al método dbos::Object::needUpdate () que se ejecuta antes de
+         realizar ninguna operacion sobre el medio fisico, si devuelve 'true' cargaria la
+         informacion mediante el dbos::Loader correspondiente y se invocaria al
+         método dbos::Object::hasChange (dbos::Loader&).
+      */
+      ReadWrite,
+      /**
+         Comprueba la recarga del objeto cada vez que se accede a el. Se invocara al método dbos::Object::needUpdate () que se ejecuta antes de
+         realizar ninguna operacion sobre el medio fisico, si devuelve 'true' cargaria la
+         informacion mediante el dbos::Loader correspondiente y se invocaria al
+         método dbos::Object::hasChange (dbos::Loader&).
+      */
+      ReadEver
+    };
+
+    /*
+       Devuelve el literal correspondiente al codigo recibido.
+       \param v Codigo a traducir a literal.
+       \return el literal correspondiente al codigo recibido.
+    */
+    static const char* asString(const _v v) throw();
+  };
+
+  /**
+     Flags usados para marcar los registros cargados en memoria.
+     \warning Exclusivamente uso interno.
+  */
+  struct Flag {
+    enum _v {
+      None = 0, Dirty = 1, Incoherent = 2, Empty = 4, HasHole = 8, Ready = 16, InProgress = 32,
+      NoDirty = ~Dirty, NoIncoherent = ~Incoherent, NoEmpty = ~Empty, NoHasHole = ~HasHole, NoReady = ~Ready, Done = ~InProgress
+    };
+  };
+
+  /**
+     Tamaños normalizados del área de almacenamiento.
+
+     @see StorageArea
+  */
+  struct StandardSize {
+    enum Value {
+      Tiny = 16, /**< Intenta que el número de registros cargados no supere los 16 registros. */
+      Little = 64, /**< Intenta que el número de registros cargados no supere los 64 registros. */
+      Small = 256, /**<Intenta que el número de registros cargados no supere los 256 registros.*/
+      Medium = 2048, /**<Intenta que el número de registros cargados no supere los 2048 registros.*/
+      Large = 8192, /**<Intenta que el número de registros cargados no supere los 8192 registros.*/
+      Huge = 32768, /**<Intenta que el número de registros cargados no supere los 32768 registros.*/
+      LargeHuge = 65536, /**<Intenta que el número de registros cargados no supere los  65536 registros.*/
+      Biggest = 131072 /**<Intenta que el número de registros cargados no supere los 131072 registros.*/
+    };
+  };
+
+  /**
+     Valor que hay que indicar al crear el área de almacenamiento (ver anna::dbos::Repository::createStorageArea)
+     para que el método #instance no devuelva excepcion de ejecucion en caso de no encontrar el
+     registro buscado.
+  */
+  static const int NoExceptionWhenNotFound = -1;
+
+  typedef std::vector <Block*> Blocks; /**< Estructura para mantener los bloques de objetos */
+  typedef std::map <Index, Instance*>::iterator iterator; /**< Definicion para recorrer los objetos del área de almacenamiento */
+  typedef std::map <Index, Instance*>::const_iterator const_iterator; /**< Definicion para recorrer los objetos del área de almacenamiento */
+
+  /**
+     Destructor.
+  */
+  virtual ~StorageArea();
+
+  /**
+   * Devuelve el código de error asociado a la excepción cuando no se encuentra un registro buscado.
+   * \return el código de error asociado a la excepción cuando no se encuentra un registro buscado.
+   */
+  int getErrorCode() const throw() { return a_errorCode; }
+
+  /*
+   * Devuelve el nombre de la este área de almacenamiento.
+   * \return el nombre de la este área de almacenamiento.
+   */
+  const std::string& getName() const throw() { return a_name; }
+
+  /**
+     Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
+     una clase C++.
+
+     Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+     debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
+     en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
+     otra combinacion de columnas que lo identifiquen univocamente.
+
+     \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
+     \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
+     que deseamos cargar en memoria.
+
+     \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
+     que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
+     caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
+
+     \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+     cuando dejemos de usar la instancia.
+  */
+  Object* instance(dbms::Connection& connection, Loader& loader) throw(RuntimeException, dbms::DatabaseException) {
+    return instance(&connection, loader);
+  }
+
+  /**
+     Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
+     una clase C++.
+
+     Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+     debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
+     en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
+     otra combinacion de columnas que lo identifiquen univocamente.
+
+     \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
+     \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
+     que deseamos cargar en memoria.
+
+     \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
+     que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
+     caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
+
+     \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+     cuando dejemos de usar la instancia.
+  */
+  Object* instance(dbms::Connection* connection, Loader& loader) throw(RuntimeException, dbms::DatabaseException);
+
+  /**
+     Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
+     una clase C++.
+
+     Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+     debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
+     en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
+     otra combinacion de columnas que lo identifiquen univocamente.
+
+     \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
+     \param  crossedLoader Cargador encargado de encontrar la clave principal a aplicar con el #Loader
+     recibido como parámetro en base a una clave alternativa contenida en el mismo.
+     \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
+     que deseamos cargar en memoria.
+
+     \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
+     que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
+     caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
+
+     \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+     cuando dejemos de usar la instancia.
+  */
+  Object* instance(dbms::Connection& connection, CrossedLoader& crossedLoader,  Loader& loader)
+  throw(RuntimeException, dbms::DatabaseException) {
+    return instance(&connection, crossedLoader, loader);
+  }
+
+  /**
+     Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
+     una clase C++.
+
+     Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+     debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
+     en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
+     otra combinacion de columnas que lo identifiquen univocamente.
+
+     \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
+     \param  crossedLoader Cargador encargado de encontrar la clave principal a aplicar con el #Loader
+     recibido como parámetro en base a una clave alternativa contenida en el mismo.
+     \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
+     que deseamos cargar en memoria.
+
+     \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
+     que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
+     caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
+
+     \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+     cuando dejemos de usar la instancia.
+  */
+  Object* instance(dbms::Connection* connection, CrossedLoader& crossedLoader,  Loader& loader)
+  throw(RuntimeException, dbms::DatabaseException);
+
+  /**
+     Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
+     una clase C++.
+
+     Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+     debe cargar.
+
+     \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
+     que deseamos cargar en memoria.
+
+     \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
+     que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
+     caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
+
+     \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+     cuando dejemos de usar la instancia.
+     \warning Para usar este método se requiere haber re-escrito el método virtual Loader::load para que no intente
+     obtener los datos desde la base de datos.
+  */
+  Object* instance(Loader& loader) throw(RuntimeException, dbms::DatabaseException) {
+    return instance(NULL, loader);
+  }
+
+  /**
+      Crea un objeto en el área de almacenamiento un y lo prepara para ser transferido al medio fisico
+      si fuera necesario.
+
+      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+      debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
+      en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
+      otra combinacion de columnas que lo identifiquen univocamente.
+
+      \param connection Conexion usada si fuera necesario acceder al medio fisico.
+      \param creator Creador encargado de generar el objeto en el área de almacenamiento.
+
+      \return La nueva instancia que cumple el patron establecido por el creador.
+
+      \warning \li Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+      cuando dejemos de usar la instancia.
+      \li No puede usarse en las áreas de almacenamiento definidas como AccessMode::ReadOnly.
+   */
+  Object* create(dbms::Connection& connection, Creator& creator) throw(RuntimeException, dbms::DatabaseException) {
+    return create(&connection, creator);
+  }
+
+  /**
+      Crea un objeto en el área de almacenamiento un y lo prepara para ser transferido al medio fisico
+      si fuera necesario.
+
+      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+      debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
+      en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
+      otra combinacion de columnas que lo identifiquen univocamente.
+
+      \param connection Conexion usada si fuera necesario acceder al medio fisico.
+      \param creator Creador encargado de generar el objeto en el área de almacenamiento.
+
+      \return La nueva instancia que cumple el patron establecido por el creador.
+
+      \warning \li Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+      cuando dejemos de usar la instancia.
+      \li No puede usarse en las áreas de almacenamiento definidas como AccessMode::ReadOnly.
+   */
+  Object* create(dbms::Connection* connection, Creator& creator) throw(RuntimeException, dbms::DatabaseException);
+
+  /**
+      Crea un objeto en el área de almacenamiento y lo prepara para ser transferido al medio fisico
+      si fuera necesario.
+
+      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+      debe cargar.
+
+      \param creator Creador encargado de generar el objeto en el área de almacenamiento.
+
+      \return La nueva instancia que cumple el patron establecido por el creador.
+
+      \warning \li Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+      cuando dejemos de usar la instancia.
+      \li No puede usarse en las áreas de almacenamiento definidas como AccessMode::ReadOnly.
+   */
+  Object* create(Creator& creator) throw(RuntimeException, dbms::DatabaseException) { return create(NULL, creator); }
+
+  /**
+     Devuelve la informacion de un objeto cargado desde el medio fisico.
+
+     Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
+     debe buscar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
+     en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
+     otra combinacion de columnas que lo identifiquen univocamente.
+
+     \param loader Cargador de clase encargado de localizar la informacion referente al objeto buscado.
+
+     \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL si el
+     objeto no fue cargado en el área de almacenamiento.
+
+     \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+     cuando dejemos de usar la instancia.
+  */
+  Object* find(Loader& loader) throw(RuntimeException);
+
+  /**
+     Devuelve de una copia del objeto recibido como parámetro e incrementa la cuenta de utilizacion
+     asociada a la instancia.
+
+     \param object Instancia obtenida mediate el método #instance.
+
+     \return Una copia del objeto recibido como parámetro. Si el parámetro recibido es NULL devolveria NULL.
+
+     \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
+     cuando dejemos de usar la instancia.
+  */
+  Object* duplicate(const Object* object) throw(RuntimeException);
+
+  /**
+     Permite conocer si un determinado objeto esta alojado en el área de almacenamiento. No
+     cambia la cuenta de utilizacion de los objetos ni provoca cambios en las estadisticas
+     de aciertos.
+
+     \param loader Cargador de clase encargado de localizar la informacion referente al objeto buscado.
+
+     \return \em true Si el objeto identificado por el Loader esta en el área de almacenamiento o
+     \em false en otro caso.
+  */
+  bool isLoaded(const Loader& loader) throw(RuntimeException);
+
+  /**
+     Transfiere la informacion del objeto recibido como parámetro al medio fisico usando el Recorder
+     recibido como parámetro.
+
+     \param connection Conexion usada si fuera necesario acceder al medio fisico.
+     \param recorder Grabador usado para transferir los datos al medio fisico.
+  */
+  void apply(dbms::Connection& connection, Recorder& recorder) throw(RuntimeException, dbms::DatabaseException);
+
+  /**
+     Elimina la informacion del objeto recibido como parámetro del medio fisico usando el Eraser
+     recibido como parámetro.
+
+     \param connection Conexion usada si fuera necesario acceder al medio fisico.
+     \param eraser Objecto usado para eliminar los datos al medio fisico.
+
+     \warning Si la cuenta de utilizacion del objeto es 1 se liberaría en otro caso se devolvería una excepción.
+  */
+  void apply(dbms::Connection& connection, Eraser& eraser) throw(RuntimeException, dbms::DatabaseException);
+
+  /**
+     Habilita la reutilizacion del espacio de memoria ocupado por un objeto instanciado mediate #instance.
+
+     Este método no saca al objeto de la memoria de almacenamiento, sino que marca su espacio de memoria
+     como subceptible de ser reutilizado. De esta forma, si el número de objetos cargados en memoria se
+     acerca al tamaño maximo indicado en la inicializacin, cuando halla que cargar un nuevo registro se
+     reusaria el espacio libre en vez de seguir aumentando el tamaño de la memoria de almacenamiento.
+
+     \param object Instancia del objeto que vamos a liberar.
+
+     \warning Si el objeto recibido como parámetro no fue reservado mediate #instance no tiene
+     ningun efecto.
+  */
+  void release(Object** object) throw(RuntimeException);
+
+  /**
+     Elimina toda la informacion referente al objeto recibido como parámetro, siempre y cuando
+     solo tenga un unica referencia activa. Descarga el objeto de la memoria de almacenamiento,
+
+     \param object Instancia que vamos a descargar de la memoria de almacenamiento.
+
+     \warning \li Si el objeto recibido como parámetro no fue reservado mediate #instance no tiene
+     ningun efecto.
+     \li La instancia a liberar solo puede tener 1 en su cuenta de utilizacion.
+  */
+  void erase(Object** object) throw(RuntimeException);
+
+  /**
+     Marca el objeto recibido como pendiente de recarga de datos.
+
+     \param object Instancia que vamos a marcar como pendiente de recarga.
+
+     \warning \li Si el objeto recibido como parámetro no fue reservado mediate #instance no tiene
+     ningun efecto.
+     \li La instancia a marcar solo deberia tener una unica instancia en uso.
+  */
+  void dirty(Object* object) throw(RuntimeException);
+
+  /**
+     Establece el tamanho de las instancias de los objetos contenidos en este área de almacenamiento.
+     \param _sizeof Numero de bytes ocupado por cada una de las instancias.
+  */
+  void setSizeof(const Size _sizeof) throw() { a_sizeof = _sizeof + sizeof(Instance); }
+
+  /**
+     Devuelve el numero maximo de bytes teorico que puede llegar a reservar este área de almacenamiento.
+     \return el numero maximo de bytes teorico que puede llegar a reservar este área de almacenamiento.
+  */
+  Size getMaxSizeOf() const throw() { return a_maxSize * a_sizeof; }
+
+  /**
+     Devuelve el numero de bytes teorico que puede llegar a reservar este área de almacenamiento.
+     \return el numero de bytes teorico que puede llegar a reservar este área de almacenamiento.
+  */
+  Size getSizeOf() const throw() { return a_directory.size() * a_sizeof; }
+
+  /**
+     Devuelve un iterator al primero de los objetos contenido en el área del almacenamiento.
+     \return Un iterator al primero de los objetos contenido en el área del almacenamiento.
+  */
+  iterator begin() throw() { return a_directory.begin(); }
+
+  /**
+     Devuelve un iterator al primero de los objetos contenido en el área del almacenamiento.
+     \return Un iterator al primero de los objetos contenido en el área del almacenamiento.
+  */
+  const_iterator begin() const throw() { return a_directory.begin(); }
+
+  /**
+     Devuelve un iterator al fin de los objetos contenidos en el área del almacenamiento.
+     \return Un iterator al fin de los objetos contenidos en el área del almacenamiento.
+  */
+  iterator end() throw() { return a_directory.end(); }
+
+  /**
+     Devuelve un iterator al fin de los objetos contenidos en el área del almacenamiento.
+     \return Un iterator al fin de los objetos contenidos en el área del almacenamiento.
+  */
+  const_iterator end() const throw() { return a_directory.end(); }
+
+  /**
+     Devuelve el puntero sobre el que esta posicionado el iterador recibido como parámetro.
+     \return El puntero sobre el que esta posicionado el iterador recibido como parámetro.
+  */
+  static Object* data(iterator ii) throw() { return ii->second->object; }
+
+  /**
+     Devuelve el puntero sobre el que esta posicionado el iterador recibido como parámetro.
+     \return El puntero sobre el que esta posicionado el iterador recibido como parámetro.
+  */
+  static const Object* data(const_iterator ii) throw() { return ii->second->object; }
+
+  /**
+     Devuelve una cadena con la informacion referente a este área de almacenamiento.
+     \return Una cadena con la informacion referente a este área de almacenamiento.
+  */
+  std::string asString() const throw();
+
+  /**
+     Devuelve un documento XML con la informacion referente a esta instancia.
+     \param parent Nodo XML del que dependende la informacion.
+     @return un documento XML con la informacion referente a esta instancia.
+  */
+  xml::Node* asXML(xml::Node* parent) const throw();
+
+protected:
+  /**
+     Descarga del área de almacenamiento todos los objetos que estuviera cargados.
+     Este método se invoca desde anna::dbos::Repository::clear
+  */
+  void clear() throw(RuntimeException);
+
+  /**
+     Devuelve un literal con el entero recibido tratado como una cantidad en bytes.
+     \return un literal con el entero recibido tratado como un cantidad en bytes
+  */
+  static std::string asMemorySize(const Size size) throw();
+
+private:
+  typedef std::map <Index, Instance*>::value_type value_type;
+
+  friend class Holes;
+
+  class Holes {
+  public:
+    struct Mode { enum _v { ReadyToReuse, TimeWait }; };
+
+    typedef std::list <Instance*> hole_container;
+    typedef hole_container::iterator hole_iterator;
+
+    Holes() : a_size(0) {;}
+
+    bool insert(Instance* instance, const Mode::_v mode) throw();
+    void erase(Instance* instance) throw();
+    Instance* front() throw() { return a_holes.front(); }
+    int size() const throw() { return a_size; }
+    int empty() const throw() { return a_holes.empty(); }
+    void pop_front() throw() { a_holes.pop_front(); a_size --; }
+    void clear() throw() { a_holes.clear(); a_size = 0; }
+
+  private:
+    hole_container a_holes;
+    int a_size;
+  };
+
+  //------------------------------------------------------------------------
+  // - object: Puntero a la instancia con el objeto cacheado.
+  // - msHoleTime: Millisecond en el que entra en la lista de huecos.
+  // - copyCounter: Numero de copias del objeto.
+  // - flags: Flags (Dirty, Incoherent, Empty).
+  //------------------------------------------------------------------------
+  friend struct Instance;
+
+  struct Instance {
+    Object* object;
+    Counter copyCounter;
+    int flags;
+    Holes::hole_iterator holeIterator;
+
+    Instance() : copyCounter(0), object(NULL), flags(Flag::None) {;}
+  };
+
+  friend class Block;
+
+  class Block {
+  public:
+    Block(ObjectAllocator objectAllocator, const Size maxSize);
+    Instance* getInstance() throw() { return (a_size < a_maxSize) ? &a_instances [a_size ++] : NULL; }
+    void reset() throw() { a_size = 0; }
+
+  private:
+    Instance* a_instances;
+    Size a_maxSize;
+    Size a_size;
+  };
+
+  const std::string a_name;
+  const Size a_maxSize;
+  ObjectAllocator a_objectAllocator;
+  const AccessMode::_v a_accessMode;
+  int a_errorCode;
+  Size a_sizeof;
+
+  Blocks a_blocks;
+  std::map <Index, Instance*> a_directory;
+  Holes a_holes;
+  Block* a_currentBlock;
+  int a_indexBlock;
+  Counter a_hit;
+  Counter a_fault;
+  Counter a_doneReuse;
+
+  /*
+     typedef std::deque <std::pair <DBIndex> inprogress_container;
+     typedef inprogress_container::iterator inprogress_iterator;
+     inprogress_container a_inprogress;
+
+     inprogress_iterator inprogress_begin () const throw () { return a_inprogress.begin (); }
+     inprogress_iterator inprogress_end () const throw () { return a_inprogress.end (); }
+     static DBIndex index (inprogress_iterator ii) throw () { return *ii; }
+     bool isInProgress (const DBIndex index) const throw ();
+  */
+
+  /*
+   * Constructor.
+   * \warning Este método sólo debería usarse desde el método dbos::Repository::allocateStorageArea.
+   */
+  StorageArea(const char* name, const Size maxSize, ObjectAllocator, const AccessMode::_v, const int errorCode);
+  StorageArea(const StorageArea&);
+
+  Object* reload(dbms::Connection*, Loader&, Instance*) throw(RuntimeException, dbms::DatabaseException);
+  void checkIncoherence(Instance*) throw();
+  bool quickReusing(Instance*) throw();
+  void verifyStatus(StorageArea::Instance*, const bool ignoreDirty = false) throw(RuntimeException);
+  Instance* allocate() throw();
+  Instance* reuse() throw();
+
+  static Instance* instance(iterator& ii) throw() { return ii->second; }
+  static std::string asString(const Instance*) throw();
+
+  friend class Repository;
+};
+
+}
+}
+
+#endif