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"
77 /* alias para codear menos :) */
79 /** Encabezado del archivo BTree
81 * Esta estructura es para comodidad de manejo, aunque en disco
82 * ocupe block_size de tamaño.
84 struct BTreeFileHeader {
88 /** Encabezado de un bloque */
89 struct BTreeNodeHeader {
90 /** Indica a que nivel corresponde un bloque
92 * nivel == 0 : una hoja
93 * nivel != 0 : nodo intermedio
97 /** Espacio libre en el bloque
99 * El nodo empieza con free_space = block_size - sizeof (BTreeHeader)
101 unsigned int free_space;
103 /** Cantidad de elementos en el nodo */
104 unsigned int item_count;
107 /** Resultado de la búsqueda de una clave */
108 struct BTreeFindResult {
109 /** Número de nodo que contiene la clave buscada. */
111 /** Encabezado del nodo que contiene la clave. */
112 BTreeNodeHeader header;
115 /** Modelo del árbol B
117 * \param filename Nombre del archivo a crear
118 * \param block_size Tamaño de bloque a utilizar
119 * \param k_t Tipo de clave a utilizar
120 * \return Un nuevo arbol B creado o NULL en caso de error
124 BTree (const std::string &filename, unsigned int block_size, int k_t = KEY_FIXED, bool create_new_file = false);
127 /** Tipos de clave a usar */
129 KEY_FIXED, /**< Utilización de clave de longitud fija */
130 KEY_VARIABLE /**< Utilización de clave de longitud variable */
133 /** Agrega una nueva clave al árbol. */
134 void AddKey (const Clave &k);
135 /** Elimina una clave del árbol. */
136 void DelKey (const Clave &k);
137 /** Busca si existe una clave en el árbol
139 * \return Un BTreeFindResult que el usuario debe liberar.
141 BTreeFindResult *FindKey (const Clave &k);
144 /* Funciones de Alta */
145 Clave* AddKeyR (const Clave *k, uint node_num, uint &left_child, uint &right_child);
146 Clave* AddKeyOtherR (const Clave *k, uint node_num, uint &left_child, uint &right_child);
147 Clave* AddKeyLeafR (const Clave *k, uint node_num, uint &left_child, uint &right_child);
149 /* Funciones de Baja */
150 void DelKeyR (BTreeData *k, uint node, uint padre);
151 void DelKeyFromLeaf (Clave *k, uint node_num, uint padre);
152 void DelKeyFromOther (const Clave &k, BTreeFindResult *r);
153 void FindB (uint node_num, uint padre, uint &left, uint &right);
154 Clave *GetKey (uint node_num, char maxmin);
156 /* Funciones de Búsqueda */
157 BTreeFindResult *FindKeyR (const Clave *k, uint node);
159 /* Funciones de manejo de archivo */
160 void WriteFileHeader ();
162 /* Manejo de Bloques */
163 void WriteBlock (uchar *block, uint num);
164 uchar *ReadBlock (uint num);
165 uchar *NewBlock (uint &num);
167 /* Manejo de headers */
168 void ReadNodoHeader (uchar *node, BTreeNodeHeader *header);
169 void WriteNodoHeader (uchar *node, BTreeNodeHeader *header);
171 /* Manejo de claves en memoria */
172 std::list<BTreeData *> ReadKeys (uchar *node, BTreeNodeHeader &node_header);
173 void WriteKeys (uchar *node, BTreeNodeHeader &node_header, std::list<BTreeData *> &keys);
174 void DeleteKeys (std::list<BTreeData *> &keys);
176 std::string filename;
177 BTreeFileHeader header;
180 /** Apunta al archivo de datos, asi se abre solo 1 vez
182 * \todo Ver si vale la pena
189 void PrintNode (uint num);