5 /** \page page_btree Árbol B
7 * \section page_model_estructura Estructura del árbol en disco.
9 * La estructura del archivo donde se almacena el árbol es una secuencia
10 * de bloques de tamaño fijo parametrizable. Cada bloque representa un nodo
11 * del árbol, exceptuando el bloque 0 que corresponde al encabezado donde se
12 * guardan los parámetros del árbol.
15 * Bloque 0 Bloque 1 Bloque 2 Bloque N
16 * +----------+----------+----------+-----+----------+
17 * |FileHeader| Nodo 0 | Nodo 1 | ... | Nodo N-1 |
18 * +----------+----------+----------+-----+----------+
21 * Cada bloque tiene su propio encabezado siguiendo la siguiente
24 * +--------------+-----------------------------------+
25 * | BloqueHeader | Area de Claves |
26 * +--------------+-----------------------------------+
29 * El area de claves depende del tipo de arbol (INDICE o EXAHUSTIVO)
30 * y del tipo de Clave (ClaveFija o ClaveVariable).
32 * Los nodos que son "hojas" (es decir, aquellos que no tienen hijos) no
33 * tienen "punteros", por lo que el area de datos seria algo como :
35 * +--------------+--------------+--------------+--------------+
36 * | clave1,dato1 | clave2,dato2 | ............ | claveN,datoN |
37 * +--------------+--------------+--------------+--------------+
40 * El par (claveN,datoN) es representado por la clase BTreeLeafData.
42 * Ahora, los bloques intermedios tienen punteros a los hijos, y
43 * quedaria algo como :
45 * +---------+----------------------+-------+----------------------+
46 * | HijoIzq | clave1,dato1,HijoDer | ..... | claveN,datoN,HijoDer |
47 * +---------+----------------------+-------+----------------------+
50 * El puntore HijoIzq es representado en memoria por la clase BTreeChildData, y
51 * el resto por BTreeData.
53 * El tamaño de la clave es variable, por lo que la cantidad de claves
54 * que puede almacenar se basa en la cantidad de espacio libre.
56 * Para saber si hay que romper en dos un nodo, se debe ver si la clave
57 * a agregar entra en el espacio libre del nodo encontrado como "lugar
58 * de insercion". Ahora, un problema a resolver es cuando se debe
59 * juntar nodos, ya que el arbol B este es particular (Preguntar a Cerveto?).
63 * * Ver como manejar las claves de manera transparente a las APIs de
64 * agregar y de borrar (EMUFS lo solucionaba bastante bien, se puede
65 * tomar una idea simimar)
73 #include "clave_fija.h"
74 #include "clave_variable.h"
75 #include "btree_data.h"
76 #include "exception.h"
78 /* alias para codear menos :) */
80 /** Encabezado del archivo BTree
82 * Esta estructura es para comodidad de manejo, aunque en disco
83 * ocupe block_size de tamaño.
85 struct BTreeFileHeader {
89 /** Encabezado de un bloque */
90 struct BTreeNodeHeader {
91 /** Indica a que nivel corresponde un bloque
93 * nivel == 0 : una hoja
94 * nivel != 0 : nodo intermedio
98 /** Espacio libre en el bloque
100 * El nodo empieza con free_space = block_size - sizeof (BTreeHeader)
102 unsigned int free_space;
104 /** Cantidad de elementos en el nodo */
105 unsigned int item_count;
108 /** Resultado de la búsqueda de una clave */
109 struct BTreeFindResult {
110 /** Número de nodo que contiene la clave buscada. */
112 /** Encabezado del nodo que contiene la clave. */
113 BTreeNodeHeader header;
116 /** Modelo del árbol B
118 * \param filename Nombre del archivo a crear
119 * \param block_size Tamaño de bloque a utilizar
120 * \param k_t Tipo de clave a utilizar
121 * \return Un nuevo arbol B creado o NULL en caso de error
125 BTree (const std::string &filename, unsigned int block_size, int t_t = TYPE_UNIQUE, int k_t = KEY_FIXED, bool create_new_file = false);
128 /** Tipos de clave a usar */
130 KEY_FIXED, /**< Utilización de clave de longitud fija */
131 KEY_VARIABLE /**< Utilización de clave de longitud variable */
139 /** Agrega una nueva clave al árbol. */
140 void AddKey (const Clave &k);
141 /** Elimina una clave del árbol. */
142 void DelKey (const Clave &k);
143 /** Busca si existe una clave en el árbol
145 * \return Un BTreeFindResult que el usuario debe liberar.
147 BTreeFindResult *FindKey (const Clave &k);
150 /* Funciones de Alta */
151 Clave* AddKeyR (const Clave *k, uint node_num, uint &left_child, uint &right_child);
152 Clave* AddKeyOtherR (const Clave *k, uint node_num, uint &left_child, uint &right_child);
153 Clave* AddKeyLeafR (const Clave *k, uint node_num, uint &left_child, uint &right_child);
155 /* Funciones de Baja */
156 void DelKeyR (BTreeData *k, uint node, uint padre);
157 void DelKeyFromLeaf (Clave *k, uint node_num, uint padre);
158 void DelKeyFromNode (Clave *k, uint node_num, uint padre, uint left, uint right);
159 void FindBrothers (uint node_num, uint padre, uint &left, uint &right);
160 Clave *ReplaceKeyInFather (uint node_num, uint padre, Clave *k);
161 Clave *GetKey (uint node_num, char maxmin);
162 void JoinNodes (uint node1, uint node2, uint padre, int);
164 /* Funciones de Búsqueda */
165 BTreeFindResult *FindKeyR (const Clave *k, uint node);
167 /* Funciones de manejo de archivo */
168 void WriteFileHeader ();
170 /* Manejo de Bloques */
171 void WriteBlock (uchar *block, uint num);
172 uchar *ReadBlock (uint num);
173 uchar *NewBlock (uint &num);
175 /* Manejo de headers */
176 void ReadNodoHeader (uchar *node, BTreeNodeHeader *header);
177 void WriteNodoHeader (uchar *node, BTreeNodeHeader *header);
179 /* Manejo de claves en memoria */
180 std::list<BTreeData *> ReadKeys (uchar *node, BTreeNodeHeader &node_header);
181 void WriteKeys (uchar *node, BTreeNodeHeader &node_header, std::list<BTreeData *> &keys);
182 void DeleteKeys (std::list<BTreeData *> &keys);
184 /* Abreviacion de Claves */
185 void AbrevKey (std::list<BTreeData *> &lst);
186 void DeAbrevKey (std::list<BTreeData *> &lst);
188 std::string filename;
189 BTreeFileHeader header;
193 /** Apunta al archivo de datos, asi se abre solo 1 vez
195 * \todo Ver si vale la pena
202 void PrintNode (uint num);