X-Git-Url: https://git.teslayout.com/public/public/public/?a=blobdiff_plain;f=include%2Fanna%2Fdbos%2FStorageArea.hpp;fp=include%2Fanna%2Fdbos%2FStorageArea.hpp;h=0000000000000000000000000000000000000000;hb=851ff2962362fd5bad874e8ed91445b296eaca24;hp=e9bda0301f7939d88a732d1ba515d7a9fdda6ff2;hpb=78be86969d2f26a9084b0c4af6ce43d5fa4ed3fd;p=anna.git diff --git a/include/anna/dbos/StorageArea.hpp b/include/anna/dbos/StorageArea.hpp deleted file mode 100644 index e9bda03..0000000 --- a/include/anna/dbos/StorageArea.hpp +++ /dev/null @@ -1,625 +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 // - - -#ifndef anna_dbos_StorageArea_hpp -#define anna_dbos_StorageArea_hpp - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include - -#include -#include - -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, /** Blocks; /**< Estructura para mantener los bloques de objetos */ - typedef std::map ::iterator iterator; /**< Definicion para recorrer los objetos del área de almacenamiento */ - typedef std::map ::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 ::value_type value_type; - - friend class Holes; - - class Holes { - public: - struct Mode { enum _v { ReadyToReuse, TimeWait }; }; - - typedef std::list 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 a_directory; - Holes a_holes; - Block* a_currentBlock; - int a_indexBlock; - Counter a_hit; - Counter a_fault; - Counter a_doneReuse; - - /* - typedef std::deque 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