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