4 /**#*#*#*#*#**#*#*#*#*#* Private prototypes*#*#*#*#*#**#*#*#*#*#**#*#*#*/
5 /* numerando los bloques */
6 int b_plus_grabar_nodo(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_node);
7 /*NODO_B_PLUS *b_plus_leer_nodo(INDEXSPECS *idx, int num_node);*/
8 NODO_B_PLUS *b_plus_crearnodo(INDEXSPECS *idx);
9 int b_plus_destruir_nodo(NODO_B_PLUS *nodo);
10 /*int b_plus_insertar_clave(INDEXSPECS *idx, INDEX_DAT *query);*/
11 int b_plus_insert_nonfull(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_nodo, int num_nodo_padre, CLAVE clave);
12 int b_plus_split_child(INDEXSPECS *idx,NODO_B_PLUS *new_root, int ,NODO_B_PLUS* raiz);
13 /**#*#*#*#*#**#*#*#*#*#*FIN PROTOTYPES*#*#*#*#*#**#*#*#*#*#**#*#*#*#*#*/
15 /** Crea un nuevo nodo y lo inicializa */
16 NODO_B_PLUS *b_plus_crearnodo(INDEXSPECS *idx) {
18 NODO_B_PLUS *nodo = (NODO_B_PLUS*)malloc(sizeof(NODO_B_PLUS));
19 if (nodo == NULL) return NULL;
21 nodo->cant_claves = 0;
23 /* Calculamos lo que ocupan las cadenas de bytes claves + hijos */
24 nodo->claves = (int*)malloc(idx->size_claves);
25 nodo->hijos = (int*)malloc(idx->size_hijos);
26 memset(nodo->claves,-1,idx->size_claves);
27 memset(nodo->hijos,-1,idx->size_hijos);
32 /** Crea el archivo indice B+ */
33 int emufs_b_plus_crear(INDEXSPECS *idx) {
39 /* Creamos el archivo que contendra el indice */
40 fp = fopen(idx->filename, "w");
41 PERR("Creando indice con nodo raiz");
43 PERR("Error al crear el archivo");
48 /* Creamos el nodo raiz y lo guardamos el en indice */
49 raiz = b_plus_crearnodo(idx);
50 error = b_plus_grabar_nodo(idx,raiz,0);
52 /* Liberamos areas de memoria reservadas */
60 /* Inserta una nueva clave y reestructura el arbol para que quede como debe */
61 int b_plus_insertar_clave(INDEXSPECS *idx, INDEX_DAT *query)
63 NODO_B_PLUS *curnode, *padre, *new_nodo;
65 /* Comienzo leyendo la raiz, entry point de toda funcion */
66 curnode = b_plus_leer_nodo(idx,0);
67 if (curnode == NULL) return -1;
69 while ( curnode->nivel > 0 && curnode ) {
70 for(i=0; i<curnode->cant_claves; i++){
71 /* me fijo que si es mayor */
72 if ( (query->clave.i_clave > curnode->claves[i])) {
73 if ( curnode->cant_claves != i ) /* si no es la ultima clave del nodo */
74 continue; /*paso a la siguiente*/
75 else { /* si era la ultima, la clave deberia ir ahi */
76 /*cargo el proximo nodo*/
77 prox_nodo = curnode->hijos[i+1];
78 break; /*salgo del for*/
80 } else { /*si no es mayor o igual es menor*/
81 prox_nodo = curnode->hijos[i];
86 curnode = b_plus_leer_nodo(idx, prox_nodo);
88 /* aca tengo el nodo donde deberia ir la clave, y su padre */
90 if ( curnode->cant_claves < idx->size_claves/sizeof(int) ){
91 int *claves_aux = (int*)malloc(idx->size_claves);
92 int *hijos_aux = (int*)malloc(idx->size_hijos);
93 memset(claves_aux,-1,idx->size_claves);
94 memset(hijos_aux,-1,idx->size_hijos);
96 while ( (curnode->claves[i] < query->clave.i_clave) && (i < curnode->cant_claves)){
97 claves_aux[i] = curnode->claves[i];
98 hijos_aux[i] = curnode->hijos[i];
101 curnode->cant_claves++;
102 claves_aux[i] = query->clave.i_clave;
103 hijos_aux[i] = query->num_bloque;
104 for (j=i+1; j<curnode->cant_claves; j++){
105 claves_aux[j] = curnode->claves[j-1];
106 hijos_aux[j] = curnode->hijos[j-1];
108 free(curnode->claves);
109 free(curnode->hijos);
110 curnode->claves = claves_aux;
111 curnode->hijos = hijos_aux;
112 b_plus_grabar_nodo(idx, curnode, prox_nodo);
113 b_plus_destruir_nodo(curnode);
116 /* si el nodo esta lleno tengo que splitear */
117 if ( curnode->cant_claves == idx->size_claves )
124 /** Busca el nro de bloque donde se debe guardar un reg con clave X */
125 /** Si la clave entra en la raiz, la guarda, si no, busca el nodo hoja
126 donde debe ir y devuelve el bloque (en query) pero no graba la clave */
127 /** Devuelve -1 si no hay un bloque donde insertar la nueva clave */
128 int emufs_b_plus_get_bloque(INDEXSPECS *idx, INDEX_DAT *query) {
130 NODO_B_PLUS *curnode;
132 /* Comienzo leyendo la raiz, entry point de toda funcion */
133 printf ("Buscando donde insertar clave: %i\n\n",query->clave.i_clave);
134 curnode = b_plus_leer_nodo(idx,0);
135 if (curnode == NULL) return -1;
136 /* Me fijo si la raiz esta vacia */
137 if ( curnode->cant_claves == 0 ){ /* entra la clave en la raiz */
138 /* ojo que este es un caso muy particular */
139 /* aumento la cant de claves*/
140 curnode->cant_claves++;
141 /* inserto la clave en el nodo, como es la primera no hace falta ordenar nada*/
142 *(curnode->claves) = query->clave.i_clave;
143 /* En query->num_bloque viene un numero de bloque nuevo valido..*/
144 /* Le asigno al nodo del arbol el mismo numero que venia en query*/
145 *(curnode->hijos) = query->num_bloque;
146 /* Cargado el query salgo de la func, luego habra que actualizar el .dat */
147 /*grabo el nodo en el archivo*/
148 b_plus_grabar_nodo(idx, curnode, 0);
149 /* librero el nodo */
150 b_plus_destruir_nodo(curnode);
153 PERR("TENGO LA HOJA");
154 /* Mientras no encontre la hoja con la clave, busco.. */
155 /* RECORDAR QUE LAS CLAVES DEBEN ESTAR ORDENADAS PARA QUE ESTO FUNCIONE !! */
156 while (curnode->nivel > 0 && curnode){
157 /*recorro las claves hasta encontrar la primera mayor a la que quiero insertar*/
158 for(i=0; i<curnode->cant_claves; i++){
159 /* me fijo que si es mayor */
160 if ( (query->clave.i_clave > curnode->claves[i])) {
161 if ( curnode->cant_claves != i ) /* si no es la ultima clave del nodo */
162 continue; /*paso a la siguiente*/
163 else { /* si era la ultima, la clave deberia ir ahi */
164 /*cargo el proximo nodo*/
165 prox_nodo = curnode->hijos[i+1];
166 break; /*salgo del for*/
168 } else { /*si no es mayor o igual es menor*/
169 prox_nodo = curnode->hijos[i];
173 b_plus_destruir_nodo(curnode);
174 curnode = b_plus_leer_nodo(idx, prox_nodo);
177 /*cuando salgo de aca deberia tener cargado en curnode el nodo hoja que busque*/
178 for (i=0; i<curnode->cant_claves-1; i++){
179 if ( query->clave.i_clave >= curnode->claves[i] ){
180 if ( curnode->cant_claves != i ) /* si no es la ultima clave */
182 else { /* si era la ultima */
183 /* Cargo en query el numero del bloque donde deberia ir la nueva clave */
184 query->num_bloque = curnode->hijos[i];
185 b_plus_destruir_nodo(curnode);
188 } else { /* si no era mayor, era menor */
191 /* ACA PODRIAMOS RETORNAR -1 COMO CODIGO DE ERROR QUE INFORMARIA QUE NO EXISTE
192 UN NODO DONDE QUEPA LA CLAVE, ENTONCES HABRIA QUE LLAMAR A LA FUNCION QUE
193 ACTUALIZA EL ARBOL Y SE ENCARGA DE ARGREGAR LA CLAVE Y HACER EL SPLIT DE SER
195 /* Llamo a la funcion que mete una clave nueva en el arbol y le paso el bloque a donde
197 b_plus_insertar_clave(idx, query);
198 b_plus_destruir_nodo(curnode);
199 return 1; /* SE INSERTO NODO NUEVO */
201 query->num_bloque = curnode->hijos[i-1];
202 b_plus_destruir_nodo(curnode);
208 if (curnode) b_plus_destruir_nodo(curnode);
212 NODO_B_PLUS *b_plus_leer_nodo(INDEXSPECS *idx, int num_node) {
216 NODO_B_PLUS *memnode = b_plus_crearnodo(idx);
217 char *disknode = (char*)malloc(idx->tam_bloque);
219 if (disknode == NULL) return NULL;
220 if (memnode == NULL) return NULL;
223 fp = fopen(idx->filename, "r+");
226 b_plus_destruir_nodo(memnode);
230 /* Intentamos leer un nodo, sino podemos error! */
231 fseek(fp, num_node*idx->tam_bloque, SEEK_SET);
232 if (fread(disknode, idx->tam_bloque, 1, fp) != 1) {
239 /* Pudimos leer un nodo de disco, ahora lo transformamos a nodo mem */
240 memcpy(memnode,disknode,SIZE_B_PLUS_HEADER);
241 memcpy(memnode->claves,disknode+SIZE_B_PLUS_HEADER,idx->size_claves);
242 memcpy(memnode->hijos,disknode+SIZE_B_PLUS_HEADER+idx->size_claves,idx->size_hijos);
245 printf("Dumping Node_%i\n",num_node);
246 printf("Nivel: %i Cant Claves: %i\n",memnode->nivel,memnode->cant_claves);
248 for (i = 0; i < idx->size_claves/sizeof(int); ++i) printf(" %i",memnode->claves[i]);
250 for (i = 0; i < idx->size_hijos/sizeof(int); ++i) printf(" %i",memnode->hijos[i]);
251 printf("\nEnd Dump\n");
257 int b_plus_grabar_nodo(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_node)
261 fp = fopen(idx->filename, "r+");
262 if (fp == NULL) return -1;
264 fseek(fp,num_node*sizeof(NODO_B_PLUS),SEEK_SET);
265 fwrite(nodo,SIZE_B_PLUS_HEADER,1,fp);
266 fwrite(nodo->claves,idx->size_claves,1,fp);
267 fwrite(nodo->hijos,idx->size_hijos,1,fp);
273 int b_plus_destruir_nodo(NODO_B_PLUS *nodo)
281 int b_plus_insert_nonfull(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_nodo, int num_nodo_padre, CLAVE clave)
283 int i, num_nodo_hijo;
286 i = nodo->cant_claves;
287 if ( nodo->nivel == 0 ){
288 while ( i >= 1 && clave.i_clave < nodo->claves[i] ){
289 nodo->claves[i+1] = nodo->claves[i];
292 nodo->claves[i+1] = clave.i_clave;
294 b_plus_destruir_nodo(nodo);
295 b_plus_grabar_nodo(idx, nodo, num_nodo);
297 while ( i >= 1 && clave.i_clave < nodo->claves[i] )
300 num_nodo_hijo = nodo->hijos[i-1];
301 hijo = b_plus_leer_nodo(idx, num_nodo_hijo);
302 if ( hijo->cant_claves == idx->size_claves/sizeof(int) ) {
303 b_plus_split_child(idx, nodo, i, hijo);
304 if ( clave.i_clave > nodo->claves[i] )
307 b_plus_insert_nonfull(idx, hijo, num_nodo_hijo, num_nodo_padre);
309 b_plus_destruir_nodo(hijo);
313 int b_tree_insertar(INDEXSPECS *idx, CLAVE clave)
317 raiz = b_plus_leer_nodo(idx, 0);
318 if ( raiz->cant_claves == idx->size_claves/sizeof(int) ) {
319 NODO_B_PLUS *new_root = b_plus_crearnodo(idx);
320 new_root->nivel = raiz->nivel + 1;
321 new_root->hijos[0] = b_plus_get_num_nodo(idx);
322 b_plus_grabar_nodo(idx, raiz, new_root->hijos[0]);
323 b_plus_grabar_nodo(idx, new_root, 0);
324 b_plus_split_child(idx, new_root, 1, raiz);
325 b_plus_insert_nonfull(idx, new_root, 0, clave);
326 } else b_plus_insert_nonfull(idx, raiz, 0, clave);
331 int b_plus_get_num_nodo(INDEXSPECS *idx)
336 fp = fopen(idx->filename, "r+");
337 if (fp == NULL) return -1;
339 num = ftell(fp)/sizeof(NODO_B_PLUS);