Remove operation help.
[anna.git] / include / anna / dbos / StorageArea.hpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #ifndef anna_dbos_StorageArea_hpp
10 #define anna_dbos_StorageArea_hpp
11
12 #include <vector>
13 #include <map>
14 #include <list>
15 #include <deque>
16
17 #include <algorithm>
18
19 #include <anna/core/mt/Mutex.hpp>
20 #include <anna/config/defines.hpp>
21 #include <anna/core/util/SortedVector.hpp>
22
23 #include <anna/dbms/DatabaseException.hpp>
24
25 #include <anna/dbos/defines.hpp>
26 #include <anna/dbos/ObjectAllocator.hpp>
27
28 namespace anna {
29
30 namespace xml {
31 class Node;
32 }
33
34 namespace dbms {
35 class Connection;
36 }
37
38 namespace dbos {
39
40 class Accesor;
41 class Object;
42 class Creator;
43 class Loader;
44 class Recorder;
45 class Eraser;
46 class Repository;
47 class CrossedLoader;
48
49 /**
50    Area de almacenamiento de los objetos obtenidos a partir de los datos guardados en un medio
51    fisico, que normalmente seria una base de datos.
52
53    La creacion de cualquier área de almacenamiento debe hacerse mediante el método
54    anna::dbos::Repository::createStorageArea.
55
56    \warning Exclusivamente para uso interno de anna.dbos
57 */
58 class StorageArea : public Mutex {
59   struct Instance;
60   class Block;
61   class Holes;
62
63 public:
64   /**
65      Modo de acceso al área de almacenamiento.
66   */
67   struct AccessMode {
68     enum _v {
69       /**
70          Carga el objeto una vez y no lo vuelve a comprobar mientras tena un estado valido.
71          No permite la creacion de nuevos objetos.
72       */
73       ReadOnly,
74       /**
75          Carga el objeto una vez e intenta recargarlo cada vez que su cuenta de utilizacion
76          sea cero. Se invocara al método dbos::Object::needUpdate () que se ejecuta antes de
77          realizar ninguna operacion sobre el medio fisico, si devuelve 'true' cargaria la
78          informacion mediante el dbos::Loader correspondiente y se invocaria al
79          método dbos::Object::hasChange (dbos::Loader&).
80       */
81       ReadWrite,
82       /**
83          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
84          realizar ninguna operacion sobre el medio fisico, si devuelve 'true' cargaria la
85          informacion mediante el dbos::Loader correspondiente y se invocaria al
86          método dbos::Object::hasChange (dbos::Loader&).
87       */
88       ReadEver
89     };
90
91     /*
92        Devuelve el literal correspondiente al codigo recibido.
93        \param v Codigo a traducir a literal.
94        \return el literal correspondiente al codigo recibido.
95     */
96     static const char* asString(const _v v) throw();
97   };
98
99   /**
100      Flags usados para marcar los registros cargados en memoria.
101      \warning Exclusivamente uso interno.
102   */
103   struct Flag {
104     enum _v {
105       None = 0, Dirty = 1, Incoherent = 2, Empty = 4, HasHole = 8, Ready = 16, InProgress = 32,
106       NoDirty = ~Dirty, NoIncoherent = ~Incoherent, NoEmpty = ~Empty, NoHasHole = ~HasHole, NoReady = ~Ready, Done = ~InProgress
107     };
108   };
109
110   /**
111      Tamaños normalizados del área de almacenamiento.
112
113      @see StorageArea
114   */
115   struct StandardSize {
116     enum Value {
117       Tiny = 16, /**< Intenta que el número de registros cargados no supere los 16 registros. */
118       Little = 64, /**< Intenta que el número de registros cargados no supere los 64 registros. */
119       Small = 256, /**<Intenta que el número de registros cargados no supere los 256 registros.*/
120       Medium = 2048, /**<Intenta que el número de registros cargados no supere los 2048 registros.*/
121       Large = 8192, /**<Intenta que el número de registros cargados no supere los 8192 registros.*/
122       Huge = 32768, /**<Intenta que el número de registros cargados no supere los 32768 registros.*/
123       LargeHuge = 65536, /**<Intenta que el número de registros cargados no supere los  65536 registros.*/
124       Biggest = 131072 /**<Intenta que el número de registros cargados no supere los 131072 registros.*/
125     };
126   };
127
128   /**
129      Valor que hay que indicar al crear el área de almacenamiento (ver anna::dbos::Repository::createStorageArea)
130      para que el método #instance no devuelva excepcion de ejecucion en caso de no encontrar el
131      registro buscado.
132   */
133   static const int NoExceptionWhenNotFound = -1;
134
135   typedef std::vector <Block*> Blocks; /**< Estructura para mantener los bloques de objetos */
136   typedef std::map <Index, Instance*>::iterator iterator; /**< Definicion para recorrer los objetos del área de almacenamiento */
137   typedef std::map <Index, Instance*>::const_iterator const_iterator; /**< Definicion para recorrer los objetos del área de almacenamiento */
138
139   /**
140      Destructor.
141   */
142   virtual ~StorageArea();
143
144   /**
145    * Devuelve el código de error asociado a la excepción cuando no se encuentra un registro buscado.
146    * \return el código de error asociado a la excepción cuando no se encuentra un registro buscado.
147    */
148   int getErrorCode() const throw() { return a_errorCode; }
149
150   /*
151    * Devuelve el nombre de la este área de almacenamiento.
152    * \return el nombre de la este área de almacenamiento.
153    */
154   const std::string& getName() const throw() { return a_name; }
155
156   /**
157      Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
158      una clase C++.
159
160      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
161      debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
162      en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
163      otra combinacion de columnas que lo identifiquen univocamente.
164
165      \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
166      \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
167      que deseamos cargar en memoria.
168
169      \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
170      que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
171      caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
172
173      \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
174      cuando dejemos de usar la instancia.
175   */
176   Object* instance(dbms::Connection& connection, Loader& loader) throw(RuntimeException, dbms::DatabaseException) {
177     return instance(&connection, loader);
178   }
179
180   /**
181      Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
182      una clase C++.
183
184      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
185      debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
186      en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
187      otra combinacion de columnas que lo identifiquen univocamente.
188
189      \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
190      \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
191      que deseamos cargar en memoria.
192
193      \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
194      que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
195      caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
196
197      \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
198      cuando dejemos de usar la instancia.
199   */
200   Object* instance(dbms::Connection* connection, Loader& loader) throw(RuntimeException, dbms::DatabaseException);
201
202   /**
203      Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
204      una clase C++.
205
206      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
207      debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
208      en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
209      otra combinacion de columnas que lo identifiquen univocamente.
210
211      \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
212      \param  crossedLoader Cargador encargado de encontrar la clave principal a aplicar con el #Loader
213      recibido como parámetro en base a una clave alternativa contenida en el mismo.
214      \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
215      que deseamos cargar en memoria.
216
217      \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
218      que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
219      caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
220
221      \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
222      cuando dejemos de usar la instancia.
223   */
224   Object* instance(dbms::Connection& connection, CrossedLoader& crossedLoader,  Loader& loader)
225   throw(RuntimeException, dbms::DatabaseException) {
226     return instance(&connection, crossedLoader, loader);
227   }
228
229   /**
230      Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
231      una clase C++.
232
233      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
234      debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
235      en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
236      otra combinacion de columnas que lo identifiquen univocamente.
237
238      \param connection Conexion usada si fuera necesario extraer los datos del medio fisico.
239      \param  crossedLoader Cargador encargado de encontrar la clave principal a aplicar con el #Loader
240      recibido como parámetro en base a una clave alternativa contenida en el mismo.
241      \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
242      que deseamos cargar en memoria.
243
244      \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
245      que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
246      caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
247
248      \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
249      cuando dejemos de usar la instancia.
250   */
251   Object* instance(dbms::Connection* connection, CrossedLoader& crossedLoader,  Loader& loader)
252   throw(RuntimeException, dbms::DatabaseException);
253
254   /**
255      Carga la informacion de un objeto contenida en un medio fisico y la interpreta para adecuarla a
256      una clase C++.
257
258      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
259      debe cargar.
260
261      \param loader Cargador de clase encargado de localizar y obtener la informacion referente al objeto
262      que deseamos cargar en memoria.
263
264      \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL en caso de
265      que al inicializar esta clase \em errorCode se halla indicado un #NoExceptionWhenNotFound en otro
266      caso si no encuentra el objeto que cumpla el patron devolveria una excepcion de ejecucion.
267
268      \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
269      cuando dejemos de usar la instancia.
270      \warning Para usar este método se requiere haber re-escrito el método virtual Loader::load para que no intente
271      obtener los datos desde la base de datos.
272   */
273   Object* instance(Loader& loader) throw(RuntimeException, dbms::DatabaseException) {
274     return instance(NULL, loader);
275   }
276
277   /**
278       Crea un objeto en el área de almacenamiento un y lo prepara para ser transferido al medio fisico
279       si fuera necesario.
280
281       Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
282       debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
283       en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
284       otra combinacion de columnas que lo identifiquen univocamente.
285
286       \param connection Conexion usada si fuera necesario acceder al medio fisico.
287       \param creator Creador encargado de generar el objeto en el área de almacenamiento.
288
289       \return La nueva instancia que cumple el patron establecido por el creador.
290
291       \warning \li Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
292       cuando dejemos de usar la instancia.
293       \li No puede usarse en las áreas de almacenamiento definidas como AccessMode::ReadOnly.
294    */
295   Object* create(dbms::Connection& connection, Creator& creator) throw(RuntimeException, dbms::DatabaseException) {
296     return create(&connection, creator);
297   }
298
299   /**
300       Crea un objeto en el área de almacenamiento un y lo prepara para ser transferido al medio fisico
301       si fuera necesario.
302
303       Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
304       debe cargar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
305       en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
306       otra combinacion de columnas que lo identifiquen univocamente.
307
308       \param connection Conexion usada si fuera necesario acceder al medio fisico.
309       \param creator Creador encargado de generar el objeto en el área de almacenamiento.
310
311       \return La nueva instancia que cumple el patron establecido por el creador.
312
313       \warning \li Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
314       cuando dejemos de usar la instancia.
315       \li No puede usarse en las áreas de almacenamiento definidas como AccessMode::ReadOnly.
316    */
317   Object* create(dbms::Connection* connection, Creator& creator) throw(RuntimeException, dbms::DatabaseException);
318
319   /**
320       Crea un objeto en el área de almacenamiento y lo prepara para ser transferido al medio fisico
321       si fuera necesario.
322
323       Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
324       debe cargar.
325
326       \param creator Creador encargado de generar el objeto en el área de almacenamiento.
327
328       \return La nueva instancia que cumple el patron establecido por el creador.
329
330       \warning \li Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
331       cuando dejemos de usar la instancia.
332       \li No puede usarse en las áreas de almacenamiento definidas como AccessMode::ReadOnly.
333    */
334   Object* create(Creator& creator) throw(RuntimeException, dbms::DatabaseException) { return create(NULL, creator); }
335
336   /**
337      Devuelve la informacion de un objeto cargado desde el medio fisico.
338
339      Este cargador deberia tener todos los datos necesarios para localizar la informacion del objeto que
340      debe buscar. Por ejemplo, en caso de tener que obtener el objeto a partir de los datos contenidos
341      en una tabla de una base de datos deberia conocer la clave primaria del objeto a cargar, o alguna
342      otra combinacion de columnas que lo identifiquen univocamente.
343
344      \param loader Cargador de clase encargado de localizar la informacion referente al objeto buscado.
345
346      \return Una instancia que cumple el patron establecido por el cargador. Puede ser NULL si el
347      objeto no fue cargado en el área de almacenamiento.
348
349      \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
350      cuando dejemos de usar la instancia.
351   */
352   Object* find(Loader& loader) throw(RuntimeException);
353
354   /**
355      Devuelve de una copia del objeto recibido como parámetro e incrementa la cuenta de utilizacion
356      asociada a la instancia.
357
358      \param object Instancia obtenida mediate el método #instance.
359
360      \return Una copia del objeto recibido como parámetro. Si el parámetro recibido es NULL devolveria NULL.
361
362      \warning Cada llamada a este método deberia tener su correspondiente liberacion invocando a #release
363      cuando dejemos de usar la instancia.
364   */
365   Object* duplicate(const Object* object) throw(RuntimeException);
366
367   /**
368      Permite conocer si un determinado objeto esta alojado en el área de almacenamiento. No
369      cambia la cuenta de utilizacion de los objetos ni provoca cambios en las estadisticas
370      de aciertos.
371
372      \param loader Cargador de clase encargado de localizar la informacion referente al objeto buscado.
373
374      \return \em true Si el objeto identificado por el Loader esta en el área de almacenamiento o
375      \em false en otro caso.
376   */
377   bool isLoaded(const Loader& loader) throw(RuntimeException);
378
379   /**
380      Transfiere la informacion del objeto recibido como parámetro al medio fisico usando el Recorder
381      recibido como parámetro.
382
383      \param connection Conexion usada si fuera necesario acceder al medio fisico.
384      \param recorder Grabador usado para transferir los datos al medio fisico.
385   */
386   void apply(dbms::Connection& connection, Recorder& recorder) throw(RuntimeException, dbms::DatabaseException);
387
388   /**
389      Elimina la informacion del objeto recibido como parámetro del medio fisico usando el Eraser
390      recibido como parámetro.
391
392      \param connection Conexion usada si fuera necesario acceder al medio fisico.
393      \param eraser Objecto usado para eliminar los datos al medio fisico.
394
395      \warning Si la cuenta de utilizacion del objeto es 1 se liberaría en otro caso se devolvería una excepción.
396   */
397   void apply(dbms::Connection& connection, Eraser& eraser) throw(RuntimeException, dbms::DatabaseException);
398
399   /**
400      Habilita la reutilizacion del espacio de memoria ocupado por un objeto instanciado mediate #instance.
401
402      Este método no saca al objeto de la memoria de almacenamiento, sino que marca su espacio de memoria
403      como subceptible de ser reutilizado. De esta forma, si el número de objetos cargados en memoria se
404      acerca al tamaño maximo indicado en la inicializacin, cuando halla que cargar un nuevo registro se
405      reusaria el espacio libre en vez de seguir aumentando el tamaño de la memoria de almacenamiento.
406
407      \param object Instancia del objeto que vamos a liberar.
408
409      \warning Si el objeto recibido como parámetro no fue reservado mediate #instance no tiene
410      ningun efecto.
411   */
412   void release(Object** object) throw(RuntimeException);
413
414   /**
415      Elimina toda la informacion referente al objeto recibido como parámetro, siempre y cuando
416      solo tenga un unica referencia activa. Descarga el objeto de la memoria de almacenamiento,
417
418      \param object Instancia que vamos a descargar de la memoria de almacenamiento.
419
420      \warning \li Si el objeto recibido como parámetro no fue reservado mediate #instance no tiene
421      ningun efecto.
422      \li La instancia a liberar solo puede tener 1 en su cuenta de utilizacion.
423   */
424   void erase(Object** object) throw(RuntimeException);
425
426   /**
427      Marca el objeto recibido como pendiente de recarga de datos.
428
429      \param object Instancia que vamos a marcar como pendiente de recarga.
430
431      \warning \li Si el objeto recibido como parámetro no fue reservado mediate #instance no tiene
432      ningun efecto.
433      \li La instancia a marcar solo deberia tener una unica instancia en uso.
434   */
435   void dirty(Object* object) throw(RuntimeException);
436
437   /**
438      Establece el tamanho de las instancias de los objetos contenidos en este área de almacenamiento.
439      \param _sizeof Numero de bytes ocupado por cada una de las instancias.
440   */
441   void setSizeof(const Size _sizeof) throw() { a_sizeof = _sizeof + sizeof(Instance); }
442
443   /**
444      Devuelve el numero maximo de bytes teorico que puede llegar a reservar este área de almacenamiento.
445      \return el numero maximo de bytes teorico que puede llegar a reservar este área de almacenamiento.
446   */
447   Size getMaxSizeOf() const throw() { return a_maxSize * a_sizeof; }
448
449   /**
450      Devuelve el numero de bytes teorico que puede llegar a reservar este área de almacenamiento.
451      \return el numero de bytes teorico que puede llegar a reservar este área de almacenamiento.
452   */
453   Size getSizeOf() const throw() { return a_directory.size() * a_sizeof; }
454
455   /**
456      Devuelve un iterator al primero de los objetos contenido en el área del almacenamiento.
457      \return Un iterator al primero de los objetos contenido en el área del almacenamiento.
458   */
459   iterator begin() throw() { return a_directory.begin(); }
460
461   /**
462      Devuelve un iterator al primero de los objetos contenido en el área del almacenamiento.
463      \return Un iterator al primero de los objetos contenido en el área del almacenamiento.
464   */
465   const_iterator begin() const throw() { return a_directory.begin(); }
466
467   /**
468      Devuelve un iterator al fin de los objetos contenidos en el área del almacenamiento.
469      \return Un iterator al fin de los objetos contenidos en el área del almacenamiento.
470   */
471   iterator end() throw() { return a_directory.end(); }
472
473   /**
474      Devuelve un iterator al fin de los objetos contenidos en el área del almacenamiento.
475      \return Un iterator al fin de los objetos contenidos en el área del almacenamiento.
476   */
477   const_iterator end() const throw() { return a_directory.end(); }
478
479   /**
480      Devuelve el puntero sobre el que esta posicionado el iterador recibido como parámetro.
481      \return El puntero sobre el que esta posicionado el iterador recibido como parámetro.
482   */
483   static Object* data(iterator ii) throw() { return ii->second->object; }
484
485   /**
486      Devuelve el puntero sobre el que esta posicionado el iterador recibido como parámetro.
487      \return El puntero sobre el que esta posicionado el iterador recibido como parámetro.
488   */
489   static const Object* data(const_iterator ii) throw() { return ii->second->object; }
490
491   /**
492      Devuelve una cadena con la informacion referente a este área de almacenamiento.
493      \return Una cadena con la informacion referente a este área de almacenamiento.
494   */
495   std::string asString() const throw();
496
497   /**
498      Devuelve un documento XML con la informacion referente a esta instancia.
499      \param parent Nodo XML del que dependende la informacion.
500      @return un documento XML con la informacion referente a esta instancia.
501   */
502   xml::Node* asXML(xml::Node* parent) const throw();
503
504 protected:
505   /**
506      Descarga del área de almacenamiento todos los objetos que estuviera cargados.
507      Este método se invoca desde anna::dbos::Repository::clear
508   */
509   void clear() throw(RuntimeException);
510
511   /**
512      Devuelve un literal con el entero recibido tratado como una cantidad en bytes.
513      \return un literal con el entero recibido tratado como un cantidad en bytes
514   */
515   static std::string asMemorySize(const Size size) throw();
516
517 private:
518   typedef std::map <Index, Instance*>::value_type value_type;
519
520   friend class Holes;
521
522   class Holes {
523   public:
524     struct Mode { enum _v { ReadyToReuse, TimeWait }; };
525
526     typedef std::list <Instance*> hole_container;
527     typedef hole_container::iterator hole_iterator;
528
529     Holes() : a_size(0) {;}
530
531     bool insert(Instance* instance, const Mode::_v mode) throw();
532     void erase(Instance* instance) throw();
533     Instance* front() throw() { return a_holes.front(); }
534     int size() const throw() { return a_size; }
535     int empty() const throw() { return a_holes.empty(); }
536     void pop_front() throw() { a_holes.pop_front(); a_size --; }
537     void clear() throw() { a_holes.clear(); a_size = 0; }
538
539   private:
540     hole_container a_holes;
541     int a_size;
542   };
543
544   //------------------------------------------------------------------------
545   // - object: Puntero a la instancia con el objeto cacheado.
546   // - msHoleTime: Millisecond en el que entra en la lista de huecos.
547   // - copyCounter: Numero de copias del objeto.
548   // - flags: Flags (Dirty, Incoherent, Empty).
549   //------------------------------------------------------------------------
550   friend struct Instance;
551
552   struct Instance {
553     Object* object;
554     Counter copyCounter;
555     int flags;
556     Holes::hole_iterator holeIterator;
557
558     Instance() : copyCounter(0), object(NULL), flags(Flag::None) {;}
559   };
560
561   friend class Block;
562
563   class Block {
564   public:
565     Block(ObjectAllocator objectAllocator, const Size maxSize);
566     Instance* getInstance() throw() { return (a_size < a_maxSize) ? &a_instances [a_size ++] : NULL; }
567     void reset() throw() { a_size = 0; }
568
569   private:
570     Instance* a_instances;
571     Size a_maxSize;
572     Size a_size;
573   };
574
575   const std::string a_name;
576   const Size a_maxSize;
577   ObjectAllocator a_objectAllocator;
578   const AccessMode::_v a_accessMode;
579   int a_errorCode;
580   Size a_sizeof;
581
582   Blocks a_blocks;
583   std::map <Index, Instance*> a_directory;
584   Holes a_holes;
585   Block* a_currentBlock;
586   int a_indexBlock;
587   Counter a_hit;
588   Counter a_fault;
589   Counter a_doneReuse;
590
591   /*
592      typedef std::deque <std::pair <DBIndex> inprogress_container;
593      typedef inprogress_container::iterator inprogress_iterator;
594      inprogress_container a_inprogress;
595
596      inprogress_iterator inprogress_begin () const throw () { return a_inprogress.begin (); }
597      inprogress_iterator inprogress_end () const throw () { return a_inprogress.end (); }
598      static DBIndex index (inprogress_iterator ii) throw () { return *ii; }
599      bool isInProgress (const DBIndex index) const throw ();
600   */
601
602   /*
603    * Constructor.
604    * \warning Este método sólo debería usarse desde el método dbos::Repository::allocateStorageArea.
605    */
606   StorageArea(const char* name, const Size maxSize, ObjectAllocator, const AccessMode::_v, const int errorCode);
607   StorageArea(const StorageArea&);
608
609   Object* reload(dbms::Connection*, Loader&, Instance*) throw(RuntimeException, dbms::DatabaseException);
610   void checkIncoherence(Instance*) throw();
611   bool quickReusing(Instance*) throw();
612   void verifyStatus(StorageArea::Instance*, const bool ignoreDirty = false) throw(RuntimeException);
613   Instance* allocate() throw();
614   Instance* reuse() throw();
615
616   static Instance* instance(iterator& ii) throw() { return ii->second; }
617   static std::string asString(const Instance*) throw();
618
619   friend class Repository;
620 };
621
622 }
623 }
624
625 #endif