]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/indice_b.c
* Mas detalles que van surgiendo mientras voy pensando.
[z.facultad/75.06/emufs.git] / emufs / indice_b.c
1
2 #include "indice_b.h"
3 #include "common.h"
4
5 /* Cantidad de claves por nodo */
6 #define CANT_HIJOS(x) ((x->tam_bloque-sizeof(B_NodoHeader))/sizeof(B_NodoEntry))
7 #define CANT_NODOS(x) (CANT_HIJOS(x)+1)
8 #define MIN_HIJOS(x) (CANT_HIJOS(x)/2)
9
10 /* Auxiliares */
11 /** Graba el nodo en el archivo */
12 static void b_grabar_nodo(INDICE *idx, int id, char *data);
13 /** Da el ID del proximo nodo a poder ser utilizado */
14 static int b_ultimo_id(INDICE *idx);
15 /** Lee un nodo desde el archivo */
16 static char *b_leer_nodo(INDICE *idx, int id);
17 /** Crea un nodo en el archivo y lo retorna. En i se pone el ID asignado */
18 static char *b_crear_nodo(INDICE *idx, int *i);
19 /** Lee el header de un nodo y lo guarda en header */
20 static void b_leer_header(char *src, B_NodoHeader *header);
21 /** Actualiza el header de un nodo desde header */
22 static void b_actualizar_header(char *src, B_NodoHeader *header);
23 /** Retorna el array de claves del nodo (esta data modifica directamente el bloque
24  *  por eso no es necesario usar un actualizar_claves 
25  */
26 static B_NodoEntry *b_leer_claves(char *src, B_NodoHeader *header);
27 /** Inserta una clave en el nodo de manera iterativa.
28  * \param idx Índice en donde insertar la clave.
29  * \param clave Clave a insertar.
30  * \param dato Dato a insertar
31  * \param nodo_id Id del nodo en el cual insertar la nueva clave.
32  * \param nodo FIXME Nodo en donde insertar??? No entiendo por que char*.
33  * \param hijo1 Id del nodo hijo de la izquierda del insertado.
34  * \param hijo2 Id del nodo hijo de la derecha del insertado.
35  */
36 static void b_insertar_en_nodo(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo1, int hijo2);
37 /** Inserta en un nodo en el que se sabe positivamente que hay lugar. */
38 static void b_insertar_en_nodo_con_lugar(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo1, int hijo2);
39 /** Esto es para asegurar el orden de los hijos luego de partir, en el caso de que
40  *  lo que se parta sea la raiz
41  */
42 static int b_elegir_izquierdo(INDICE *idx, int a, int b);
43 /** Borra una clave del arbol */
44 static void b_borrar_clave(INDICE *idx, char *nodo, int nodo_id, CLAVE k);
45 /** Le pide al hermano derecho del nodo una clave cuando se eliminan claves */
46 static void b_pedir_clave_derecha(char *, int, char *, int, char *, int, int);
47 /** Le pide al hermano izquierdo una clave cuando se eliminan claves */
48 static void b_pedir_clave_izquierda(char *, int, char *, int, char *, int, int);
49 /** Le pasa al hermano derecho del nodo una clave cuando se insertan claves */
50 static void b_pasar_clave_a_derecha(INDICE*, char*, int, char*, int, int, B_NodoEntry);
51 /** Le pasa al hermano izquierdo una clave cuando se insertan claves */
52 static void b_pasar_clave_a_izquierda(INDICE*, char*, int, char*, int, int, B_NodoEntry);
53 /** Junta 2 nodos y hace uno solo */
54 static void b_fundir_nodo(char *, int, char *, int, char *, int, int);
55
56 void emufs_indice_b_crear(INDICE *idx)
57 {
58         FILE *fp;
59         char *bloque;
60         B_NodoHeader header;
61
62         header.cant = 0;
63         header.nivel = 0;
64         header.padre = -1;
65         header.hijo_izquierdo = -1;
66
67         fp = fopen(idx->filename, "w");
68         PERR("Creando indice");
69         fprintf(stderr, "Archivo = (%s)\n", idx->filename);
70         if (fp == NULL) {
71                 PERR("Error al crear el archivo");
72                 return;
73         }
74         
75         /* Creo el archivo con el Nodo raiz */
76         bloque = (char *)malloc(idx->tam_bloque);
77         memset(bloque, -1, idx->tam_bloque);
78
79         memcpy(bloque, &header, sizeof(B_NodoHeader));
80
81         fwrite(bloque, idx->tam_bloque, 1, fp);
82         fclose(fp);
83 }
84
85 int emufs_indice_b_insertar(INDICE *idx, CLAVE clave, INDICE_DATO dato)
86 {
87         int i, nodo_id, padre_id;
88         B_NodoHeader header;
89         B_NodoEntry *claves;
90         char *nodo, *padre;
91         
92         /* Leo la raiz */
93         nodo = b_leer_nodo(idx, 0);
94         padre_id = nodo_id = 0;
95         padre = NULL;
96         while (nodo) {
97                 if (padre) free(padre);
98                 padre = nodo;
99                 padre_id = nodo_id;
100                 b_leer_header(nodo, &header);
101                 claves = b_leer_claves(nodo, &header);
102                 i=0;
103                 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) i++;
104                 if ((i<header.cant) && (emufs_indice_es_igual(idx, claves[i].clave, clave))) {
105                         if (idx->tipo == IND_PRIMARIO) {
106                                 PERR("Indice primario no puede contener claves duplicadas!");
107                                 return 0;
108                         }
109                         
110                         /* TODO : Implementar carga de valor en clave duplicada! */
111                         
112                         return 1;
113                 } else {
114                         if (i == 0) {
115                                 nodo = b_leer_nodo(idx, header.hijo_izquierdo);
116                                 nodo_id = header.hijo_izquierdo;
117                         } else {
118                                 nodo = b_leer_nodo(idx, claves[i-1].hijo_derecho);
119                                 nodo_id = claves[i-1].hijo_derecho;
120                         }
121                 }
122         }
123
124         if (nodo) free(nodo);
125         nodo = padre;
126         nodo_id = padre_id;
127         b_insertar_en_nodo(idx, clave, dato, nodo_id, nodo, -1, -1);
128         return 1; /* Agregar OK! */
129 }
130
131 INDICE_DATO emufs_indice_b_buscar(INDICE *idx, CLAVE clave)
132 {
133         int i;
134         INDICE_DATO ret;
135         B_NodoHeader header;
136         B_NodoEntry *claves;
137         char *nodo, *tmp;
138         
139         if (idx->tipo != IND_PRIMARIO) {
140                 /* SOLO SE PUEDE BUSCAR CON CLAVE UNICA! */
141                 ret.id = ret.bloque = -1;
142                 return ret;
143         }
144         
145         /* Leo la raiz */
146         nodo = b_leer_nodo(idx, 0);
147         while (nodo) {
148                 b_leer_header(nodo, &header);
149                 claves = b_leer_claves(nodo, &header);
150                 i=0;
151                 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) i++;
152                 if (emufs_indice_es_igual(idx, claves[i].clave, clave)) {
153                                 ret = claves[i].dato;
154                                 free(nodo);
155                                 return ret;
156                 } else {
157                         tmp = nodo;
158                         if (i == 0) {
159                                 nodo = b_leer_nodo(idx, header.hijo_izquierdo);
160                         } else {
161                                 nodo = b_leer_nodo(idx, claves[i-1].hijo_derecho);
162                         }
163                         free(tmp);
164                 }
165         }
166
167         /* Nodo no encontrado */
168         ret.id = ret.bloque = -1;
169         return ret;
170 }
171
172 int emufs_indice_b_borrar(INDICE *idx, CLAVE k)
173 {
174         /* Busco el nodo que contiene la clave,si es que esta existe */
175         char *nodo;
176         int nodo_id, i;
177         char encontrado=0;
178         B_NodoHeader header;
179         B_NodoEntry *claves;
180
181         nodo_id = 0; /* Tomo la raiz */
182         nodo = b_leer_nodo(idx, nodo_id);
183         PERR("Buscando clave a borrar");
184         while (nodo && !encontrado) {
185                 /* Obtengo los datos del nodo */
186                 b_leer_header(nodo, &header);
187                 claves = b_leer_claves(nodo, &header);
188
189                 i=0;
190                 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, k))) i++;
191
192                 if ((emufs_indice_es_igual(idx, claves[i].clave, k)) && (i<header.cant))
193                         encontrado = 1;
194                 else {
195                         if (i==0) {
196                                 free(nodo);
197                                 nodo_id = header.hijo_izquierdo;
198                                 nodo = b_leer_nodo(idx, nodo_id);
199                         } else {
200                                 nodo_id = claves[i-1].hijo_derecho;
201                                 free(nodo);
202                                 nodo = b_leer_nodo(idx, nodo_id);
203                         }
204                 }
205         }
206
207         if (encontrado) {
208                 PERR("Clave encontrada, borrando ...");
209                 b_borrar_clave(idx, nodo, nodo_id, k);
210         } else {
211                 PERR("Clave no encontrada");
212         }
213         return 0;
214 }
215
216 static int b_ultimo_id(INDICE *idx)
217 {
218         int i;
219         FILE *fp;
220         fp = fopen(idx->filename, "r");
221         fseek(fp, 0, SEEK_END);
222         i = ftell(fp)/idx->tam_bloque;
223         fclose(fp);
224
225         return i;
226 }
227
228 static char *b_crear_nodo(INDICE *idx, int *id)
229 {
230         char *bloque;
231         B_NodoHeader header;
232
233         (*id) = b_ultimo_id(idx);
234
235         header.cant = 0;
236         header.nivel = 0;
237         header.hijo_izquierdo = -1;
238         header.padre = -1;
239
240         bloque = (char *)malloc(idx->tam_bloque);
241         memset(bloque, -1, idx->tam_bloque);
242         memcpy(bloque, &header, sizeof(B_NodoHeader));
243
244         b_grabar_nodo(idx, *id, bloque);
245
246         return bloque;
247 }
248
249 static char *b_leer_nodo(INDICE *idx, int id)
250 {
251         FILE *fp;
252         char *out;
253
254         if (id < 0) return NULL;
255
256         fp = fopen(idx->filename, "r");
257         if (fp == NULL) return NULL;
258
259         fseek(fp, id*idx->tam_bloque, SEEK_SET);
260
261         out = (char *)malloc(idx->tam_bloque);
262         if (out == NULL) {
263                 fclose(fp);
264                 return NULL;
265         }
266
267         if (fread(out, 1, idx->tam_bloque, fp) != idx->tam_bloque) {
268                 free(out);
269                 /* No se puso leer el nodo */
270                 fclose(fp);
271                 return NULL;
272         }
273
274         fclose(fp);
275         return out;
276 }
277
278 static void b_grabar_nodo(INDICE *idx, int id, char *data)
279 {
280         FILE *fp;
281
282 /*      if (id > b_ultimo_id()) {
283                 printf("AGREGANDO AL FINAL\n");
284                 fp = fopen(FILENAME, "a");
285                 if (fp == NULL) {
286                 _("No se pudo abrir archivo\n");
287                         return;
288                 }
289         } else {
290                 fp = fopen(FILENAME, "w");
291                 if (fp == NULL) {
292                 _("No se pudo abrir archivo\n");
293                         return;
294                 }
295                 fseek(fp, id*BLOCK_SIZE, SEEK_SET);
296                 printf("SOLO GUARDO DATA\n");
297         }*/
298
299         fp = fopen(idx->filename, "r+");
300         fseek(fp, id*idx->tam_bloque, SEEK_SET);
301         fwrite(data, 1, idx->tam_bloque, fp);
302         fclose(fp);
303 }
304
305 static void b_leer_header(char *src, B_NodoHeader *header)
306 {
307         if (!src) return;
308
309         memcpy(header, src, sizeof(B_NodoHeader));
310 }
311
312 static void b_actualizar_header(char *src, B_NodoHeader *header)
313 {
314         if (!src) return;
315         memcpy(src, header, sizeof(B_NodoHeader));
316 }
317
318 static B_NodoEntry *b_leer_claves(char *src, B_NodoHeader *header)
319 {
320         return (B_NodoEntry *)(src+sizeof(B_NodoHeader));
321 }
322
323 static void b_insertar_en_nodo(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo1, int hijo2)
324 {
325         char *padre, *nuevo;
326         int nuevo_id;
327         int i, j;
328         static int rompi=0;
329         char salir = 0;
330         B_NodoHeader nodo_header, nuevo_header;
331         B_NodoEntry *claves, *tmp_claves, *claves_nuevo;
332
333         do {
334                 if (!nodo) {
335                         /* CREAR NODO? */
336                         nodo = b_crear_nodo(idx, &nodo_id);
337                 }
338                 b_leer_header(nodo, &nodo_header);
339                 claves = b_leer_claves(nodo, &nodo_header);
340
341                 padre = b_leer_nodo(idx, nodo_header.padre);
342
343                 if (nodo_header.cant == CANT_HIJOS(idx)) {
344                         int total;
345                         /* TODO: Si es B*, hay que chequear si alguno de los 2
346                          *       nodos hermanos pueden prestarme espacio (y
347                          *       desplazar si es así). Si no pueden, hay que
348                          *       hacer un split de 2 nodos en 3.
349                          *       Si no es B*, hay que hacer lo que sigue:
350                          */
351                         nuevo = b_crear_nodo(idx, &nuevo_id);
352                         i=0;
353                         /* Creo una lista ordenada de los nodos a partir */
354                         tmp_claves = (B_NodoEntry *)malloc(sizeof(B_NodoEntry)*(nodo_header.cant+1));
355                         total = nodo_header.cant;
356                         while ((i<nodo_header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) {
357                                 tmp_claves[i] = claves[i];
358                                 i++;
359                         }
360                         tmp_claves[i].clave = clave;
361                         tmp_claves[i].dato = dato;
362                         tmp_claves[i].hijo_derecho = hijo1;
363                         tmp_claves[i+1].hijo_derecho = hijo2;
364                         while (i < nodo_header.cant) {
365                                 tmp_claves[i+1] = claves[i];
366                                 i++;
367                         }
368                         
369                         /* Asigno a cada nodo lo que corresponde */
370                         b_leer_header(nuevo, &nuevo_header);
371
372                         nuevo_header.nivel = nodo_header.nivel;
373                         nodo_header.cant = total/2;
374                         nuevo_header.cant = total - nodo_header.cant;
375
376                         memset(claves, '*', idx->tam_bloque-sizeof(B_NodoHeader));
377                         for(j=0; j<nodo_header.cant; j++)
378                                 claves[j] = tmp_claves[j];
379
380                         claves_nuevo = b_leer_claves(nuevo, &nuevo_header);
381                         memset(claves_nuevo, '*', idx->tam_bloque-sizeof(B_NodoHeader));
382                         for(j=0; j<nuevo_header.cant; j++)
383                                 claves_nuevo[j] = tmp_claves[j+total/2+1];
384
385                         b_actualizar_header(nodo, &nodo_header);
386                         b_actualizar_header(nuevo, &nuevo_header);
387
388                         if (nodo_id != 0) {
389                                 clave = tmp_claves[total/2].clave;
390                                 /* XXX dato.bloque = nuevo_id; */
391
392                                 b_grabar_nodo(idx, nodo_id, nodo);
393                                 b_grabar_nodo(idx, nuevo_id, nuevo);
394                                 free(nodo);
395                                 free(nuevo);
396                                 free(tmp_claves);
397
398                                 hijo1 = nodo_id;
399                                 hijo2 = nuevo_id;
400
401                                 nodo = padre;
402                                 nodo_id = nodo_header.padre;
403                         } else {
404                                 /* Oops, parti el raiz, y este debe quedar en 0, lo paso a otro bloque
405                                  * y dejo el padre vacio
406                                  */
407                                 char *tmp_nuevo = b_crear_nodo(idx, &nodo_id);
408                                 memcpy(tmp_nuevo, nodo, idx->tam_bloque);
409                                 free(nodo);
410                                 nodo = tmp_nuevo;
411         
412                                 clave = tmp_claves[total/2].clave;
413                                 /* XXX dato.bloque = nuevo_id; */
414
415                                 b_grabar_nodo(idx, nuevo_id+1, nodo);
416                                 b_grabar_nodo(idx, nuevo_id, nuevo);
417                 
418                                 free(nodo);
419                                 free(nuevo);
420                                 free(tmp_claves);
421
422                                 hijo1 = nuevo_id+1;
423                                 hijo2 = nuevo_id;
424
425                                 /* Limpio al padre */
426                                 nuevo = b_leer_nodo(idx, 0);
427
428                                 b_leer_header(nuevo, &nuevo_header);
429                                 nuevo_header.cant = 0;
430                                 nuevo_header.padre = -1;
431                                 nuevo_header.nivel = nodo_header.nivel+1;
432                                 memset(nuevo, -1, idx->tam_bloque);
433                                 b_actualizar_header(nuevo, &nuevo_header);
434                                 b_grabar_nodo(idx, 0, nuevo);
435
436                                 nodo_id = 0;
437                                 nodo = nuevo;
438                                 rompi = 1;
439                         }
440                 } else {
441                         /* La clave entra en este nodo!! */
442                         b_insertar_en_nodo_con_lugar(idx, clave, dato, nodo_id, nodo, hijo1, hijo2);
443                         salir = 1;
444                 }
445         } while (!salir);
446 }
447
448 void b_insertar_en_nodo_con_lugar(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo1, int hijo2)
449 {
450         int i = 0;
451         B_NodoHeader nodo_header;
452         B_NodoEntry* claves;
453         b_leer_header(nodo, &nodo_header);
454         claves = b_leer_claves(nodo, &nodo_header);
455         if (nodo_header.cant > 0) {
456                 int j;
457                 while ((emufs_indice_es_menor(idx, claves[i].clave, clave)) && (i < nodo_header.cant)) i++;
458                 for(j=nodo_header.cant; j > i; j--)
459                         claves[j] = claves[j-1];
460         }
461         nodo_header.cant++;
462         claves[i].clave = clave;
463         claves[i].dato = dato;
464         claves[i].hijo_derecho = hijo2;
465         nodo_header.hijo_izquierdo = b_elegir_izquierdo(idx, nodo_header.hijo_izquierdo, hijo1);
466
467         b_actualizar_header(nodo, &nodo_header);
468         b_grabar_nodo(idx, nodo_id, nodo);
469
470         /* Debo actualizar los punteros al padre de los hijos */
471         if (hijo1 != -1) {
472                 char* nuevo = b_leer_nodo(idx, hijo1);
473                 if (nuevo != NULL) {
474                         B_NodoHeader nuevo_header;
475                         b_leer_header(nuevo, &nuevo_header);
476                         nuevo_header.padre = nodo_id;
477                         b_actualizar_header(nuevo, &nuevo_header);
478                         b_grabar_nodo(idx, hijo1, nuevo);
479                         free(nuevo);
480                 } else printf("FUCK! hijo1=%d no existe!\n", hijo1);
481         }
482         if (hijo2 != -1) {
483                 char* nuevo = b_leer_nodo(idx, hijo2);
484                 if (nuevo != NULL) {
485                         B_NodoHeader nuevo_header;
486                         b_leer_header(nuevo, &nuevo_header);
487                         nuevo_header.padre = nodo_id;
488                         b_actualizar_header(nuevo, &nuevo_header);
489                         b_grabar_nodo(idx, hijo2, nuevo);
490                         free(nuevo);
491                 } else printf("FUCK! hijo2=%d no existe!\n", hijo2);
492         }
493 }
494
495 static int b_elegir_izquierdo(INDICE *idx, int a, int b)
496 {
497         int cual;
498         char *nodo1, *nodo2;
499         B_NodoHeader header1, header2;
500         B_NodoEntry *claves1, *claves2;
501
502         if (a==-1) return b;
503         if (b==-1) return a;
504
505         nodo1 = b_leer_nodo(idx, a);
506         nodo2 = b_leer_nodo(idx, b);
507
508         b_leer_header(nodo1, &header1);
509         b_leer_header(nodo2, &header2);
510
511         claves1 = b_leer_claves(nodo1, &header1);
512         claves2 = b_leer_claves(nodo2, &header2);
513
514         if (emufs_indice_es_menor(idx, claves1[0].clave, claves2[0].clave))
515                 cual = a;
516         else
517                 cual = b;
518
519         free(nodo1);
520         free(nodo2);
521         return cual;
522 }
523
524 INDICE_DATO *emufs_indice_b_buscar_muchos(INDICE *idx, CLAVE clave, int *cant)
525 {
526         /* Si el indice es primario no tiene sentido hacer nada */
527         if (idx->funcion == IND_PRIMARIO) {
528                 *cant = 0;
529                 return NULL;
530         }
531
532         /* TODO Implementar indices con repeticion */
533         return NULL;
534 }
535
536 static void b_borrar_clave(INDICE *idx, char *nodo, int nodo_id, CLAVE k)
537 {
538         int pos, actual_id, padre_id, i, pos_padre, izquierda_id, derecha_id;
539         B_NodoHeader header, header_actual, header_padre, header_izq, header_der;
540         B_NodoEntry *claves, *claves_actual, *claves_padre;/*, *claves_izq, *claves_der;*/
541         char *actual, *padre, *izq, *der;
542
543         b_leer_header(nodo, &header);
544         claves = b_leer_claves(nodo, &header);
545
546         pos = 0;
547         /* Busco la posicion dentro de la lista de claves */
548         while (emufs_indice_es_menor(idx, claves[pos].clave, k)) pos++;
549
550         /* Es el nodo una hoja? */
551         if (header.hijo_izquierdo != -1) {
552                 /* No!, es un nodo intermedio!! */
553                 if (pos == 0)
554                         actual = b_leer_nodo(idx, header.hijo_izquierdo);
555                 else
556                         actual = b_leer_nodo(idx, claves[pos+1].hijo_derecho);
557
558                 b_leer_header(actual, &header_actual);
559                 while (header_actual.hijo_izquierdo != -1) {
560                         actual_id = header_actual.hijo_izquierdo;
561                         free(actual);
562                         actual = b_leer_nodo(idx, actual_id);
563                         b_leer_header(actual, &header_actual);
564                 }
565                 claves_actual = b_leer_claves(actual, &header);
566
567                 claves[pos] = claves_actual[0];
568                 pos = 0;
569                 b_grabar_nodo(idx, nodo_id, nodo);
570         } else {
571                 actual = nodo;
572         }
573
574         /* Borro la clave */
575         for(i=pos; i < header_actual.cant; i++) {
576                 claves_actual[i] = claves_actual[i+1];
577         }
578         header_actual.cant--;
579         /* Guardo los cambios */
580         b_actualizar_header(actual, &header_actual);
581         b_grabar_nodo(idx, actual_id, actual);
582
583         /* Se cumple la condicion de hijos? */
584         if (header_actual.cant >= MIN_HIJOS(idx)) {
585                 PERR("Borrar completo sin fundir");
586                 return;
587         }
588
589         /* Tengo que pasar datos o fundir nodos :-( */
590         do {
591                 padre_id = header.padre;
592                 padre = b_leer_nodo(idx, padre_id);
593                 b_leer_header(padre, &header_padre);
594                 claves_padre = b_leer_claves(padre, &header_padre);
595                 /* TODO Tengo el hijo_izquierdo para revisar!! XXX */
596                 if (header_padre.hijo_izquierdo == actual_id) {
597                         izquierda_id = -1; /* No tengo hermano izquierdo */
598                         /* Mi hermano derecho es el primer nodo del padre */
599                         derecha_id = claves_padre[0].hijo_derecho;
600                         der = b_leer_nodo(idx, derecha_id);
601                         b_leer_header(der, &header_der);
602                 } else {
603                         for(pos_padre=0; claves_padre[pos_padre].hijo_derecho != actual_id; pos_padre++)        {       }
604
605                         /* Busco mis hermanos a derecha e izquierda, si es que existen */
606                         if (pos_padre >= 0) {
607                                 if (pos_padre == 0)
608                                         izquierda_id = header_padre.hijo_izquierdo;
609                                 else
610                                         izquierda_id = claves_padre[pos_padre-1].hijo_derecho;
611                                 izq = b_leer_nodo(idx, izquierda_id);
612                                 b_leer_header(izq, &header_izq);
613                         } else {
614                                 izquierda_id = -1;
615                         }
616                         if (pos_padre < header_padre.cant) {
617                                 derecha_id = claves_padre[pos_padre+1].hijo_derecho;
618                                 der = b_leer_nodo(idx, derecha_id);
619                                 b_leer_header(der, &header_der);
620                         } else {
621                                 derecha_id = -1;
622                         }
623                 }
624                 /* Intendo pasar una clave desde un hermano hacia mi */
625                 if ((derecha_id != -1) && (header_der.cant > MIN_HIJOS(idx))) {
626                         b_pedir_clave_derecha(der, derecha_id, padre, padre_id, actual, actual_id, pos_padre);
627                 } else if ((izquierda_id != -1) && (header_izq.cant > MIN_HIJOS(idx))) {
628                         b_pedir_clave_izquierda(izq, izquierda_id, padre, padre_id, actual, actual_id, pos_padre-1);
629                 } else {
630                         /* No pude pasar clave, tengo que fundir :-( */
631                         if (derecha_id != -1) {
632                                 b_fundir_nodo(actual, actual_id, padre, padre_id, der, derecha_id, pos_padre);
633                         } else {
634                                 b_fundir_nodo(izq, izquierda_id, padre, padre_id, actual, actual_id, pos_padre-1);
635                         }
636                 }
637
638                 /* TODO que guardo ?, todo ? */
639                 b_grabar_nodo(idx, actual_id, actual);
640                 b_grabar_nodo(idx, izquierda_id, izq);
641                 b_grabar_nodo(idx, derecha_id, der);
642                 b_grabar_nodo(idx, padre_id, padre);
643                 if (actual_id != -1) free(actual);
644                 /*if (padre_id != -1) free(padre);*/
645                 if (derecha_id != -1) free(der);
646                 if (izquierda_id != -1) free(izq);
647                 actual = padre;
648                 actual_id = padre_id;
649         } while ((actual_id != -1) && (header_actual.cant < MIN_HIJOS(idx)));
650 }
651
652 static void b_pedir_clave_derecha(char *der, int der_id, char *padre, int padre_id, char *nodo, int nodo_id, int pos_clave)
653 {
654         int i;
655         B_NodoHeader h_der, h_padre, h_nodo;
656         B_NodoEntry *c_der, *c_padre, *c_nodo;
657
658         b_leer_header(nodo, &h_nodo);
659         c_nodo = b_leer_claves(nodo, &h_nodo);
660         b_leer_header(der, &h_der);
661         c_der = b_leer_claves(der, &h_der);
662         b_leer_header(padre, &h_padre);
663         c_padre = b_leer_claves(padre, &h_padre);
664
665         c_nodo[h_nodo.cant] = c_padre[pos_clave];
666         c_nodo[h_nodo.cant].hijo_derecho = -1; /* XXX */
667
668         c_padre[pos_clave] = c_der[0];
669         c_padre[pos_clave].hijo_derecho = der_id;
670         
671         /* Muevo las claves de derecho */
672         for(i=0; i<h_der.cant; i++) {
673                 c_der[i] = c_der[i+1];
674         }
675         h_der.cant--;
676         h_nodo.cant++;
677
678         b_actualizar_header(der, &h_der);
679         b_actualizar_header(nodo, &h_nodo);
680 }
681
682 void b_pasar_clave_a_derecha(INDICE *idx, char *der, int der_id, char *padre, int padre_id, int padre_pos, B_NodoEntry entry)
683 {
684         B_NodoHeader der_h, padre_h;
685         B_NodoEntry *der_entries, *padre_entries;
686         /* Leo claves y cabecera del nodo de la derecha y del padre */
687         b_leer_header(der, &der_h);
688         der_entries = b_leer_claves(der, &der_h);
689         b_leer_header(padre, &padre_h);
690         padre_entries = b_leer_claves(padre, &padre_h);
691         /* Inserto en el hijo derecho la clave del padre */
692         b_insertar_en_nodo_con_lugar(idx, padre_entries[padre_pos].clave, padre_entries[padre_pos].dato,
693                         der_id, der, entry.hijo_derecho, der_h.hijo_izquierdo);
694         /* Reemplazo clave del padre por clave nueva */
695         entry.hijo_derecho = der_id;
696         padre_entries[padre_pos] = entry;
697 }
698
699 void b_pedir_clave_izquierda(char *izq, int izq_id, char *padre, int padre_id, char *nodo, int nodo_id, int pos_clave)
700 {
701         int i;
702         B_NodoHeader h_izq, h_padre, h_nodo;
703         B_NodoEntry *c_izq, *c_padre, *c_nodo;
704
705         b_leer_header(nodo, &h_nodo);
706         c_nodo = b_leer_claves(nodo, &h_nodo);
707         b_leer_header(izq, &h_izq);
708         c_izq = b_leer_claves(izq, &h_izq);
709         b_leer_header(padre, &h_padre);
710         c_padre = b_leer_claves(padre, &h_padre);
711
712         for(i=h_nodo.cant; i>0;i++)
713                 c_nodo[i] = c_nodo[i-1];
714
715         h_nodo.cant++;
716         c_nodo[0] = c_padre[pos_clave];
717         c_nodo[0].hijo_derecho = -1; /* XXX */
718         c_padre[pos_clave] = c_izq[h_izq.cant-1];
719         c_padre[pos_clave].hijo_derecho = izq_id;
720         h_izq.cant--;
721
722         b_actualizar_header(izq, &h_izq);
723         b_actualizar_header(padre, &h_padre);
724         b_actualizar_header(nodo, &h_nodo);
725 }
726
727 void b_pasar_clave_a_izquierda(INDICE* idx, char *izq, int izq_id, char *padre, int padre_id, int padre_pos, B_NodoEntry entry)
728 {
729 /*      int i;
730         B_NodoHeader h_izq, h_padre, h_nodo;
731         B_NodoEntry *c_izq, *c_padre, *c_nodo;
732
733         b_leer_header(nodo, &h_nodo);
734         c_nodo = b_leer_claves(nodo, &h_nodo);
735         b_leer_header(izq, &h_izq);
736         c_izq = b_leer_claves(izq, &h_izq);
737         b_leer_header(padre, &h_padre);
738         c_padre = b_leer_claves(padre, &h_padre);
739
740         for(i=h_nodo.cant; i>0;i++)
741                 c_nodo[i] = c_nodo[i-1];
742
743         h_nodo.cant++;
744         c_nodo[0] = c_padre[pos_clave];
745         c_nodo[0].hijo_derecho = -1; / * XXX * /
746         c_padre[pos_clave] = c_izq[h_izq.cant-1];
747         c_padre[pos_clave].hijo_derecho = izq_id;
748         h_izq.cant--;
749
750         b_actualizar_header(izq, &h_izq);
751         b_actualizar_header(padre, &h_padre);
752         b_actualizar_header(nodo, &h_nodo);
753 */
754 }
755
756 static void b_fundir_nodo(char *izq, int izq_id, char *padre, int padre_id, char *der, int der_id, int pos_clave)
757 {
758 }
759