--- /dev/null
+// 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