7 /* Cantidad de claves por nodo */
8 #define CANT_HIJOS(x) ((x->tam_bloque-sizeof(B_NodoHeader))/sizeof(B_NodoEntry))
9 #define CANT_NODOS(x) (CANT_HIJOS(x)+1)
10 #define MIN_HIJOS(x) (CANT_HIJOS(x)/2)
13 /** Graba el nodo en el archivo */
14 static void b_grabar_nodo(INDICE *idx, int id, char *data);
15 /** Da el ID del proximo nodo a poder ser utilizado */
16 static int b_ultimo_id(INDICE *idx);
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 /** Actualiza el header de un nodo desde header */
20 static void b_actualizar_header(char *src, B_NodoHeader *header);
21 /** Inserta una clave en el nodo de manera iterativa.
22 * \param idx Índice en donde insertar la clave.
23 * \param clave Clave a insertar.
24 * \param dato Dato a insertar
25 * \param nodo_id Id del nodo en el cual insertar la nueva clave.
26 * \param nodo FIXME Nodo en donde insertar??? No entiendo por que char*.
27 * \param hijo1 Id del nodo hijo de la izquierda del insertado.
28 * \param hijo2 Id del nodo hijo de la derecha del insertado.
30 static void b_insertar_en_nodo(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo_izq, int hijo_der);
31 /** Inserta en un nodo en el que se sabe positivamente que hay lugar. */
32 static void b_insertar_en_nodo_con_lugar(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo_izq, int hijo_der);
33 /** Borra una clave del arbol */
34 static void b_borrar_clave(INDICE *idx, char *nodo, int nodo_id, CLAVE k);
35 /** Le pide al hermano derecho del nodo una clave cuando se eliminan claves */
36 static void b_pedir_clave_derecha(char *, int, char *, int, char *, int, int);
37 /** Le pide al hermano izquierdo una clave cuando se eliminan claves */
38 static void b_pedir_clave_izquierda(char *, int, char *, int, char *, int, int);
39 /** Le pasa al hermano derecho del nodo una clave cuando se insertan claves */
40 static void b_pasar_clave_a_derecha(INDICE*, char*, int, char*, int, int, B_NodoEntry);
41 /** Le pasa al hermano izquierdo una clave cuando se insertan claves */
42 static void b_pasar_clave_a_izquierda(INDICE*, char*, int, char*, int, int, B_NodoEntry, int, int);
43 /** Junta 2 nodos y hace uno solo */
44 static void b_fundir_nodo(INDICE *,char *, int, char *, int, char *, int, int);
45 /** Crea 3 nodos a partir de 2 llenos */
46 static void b_partir_dos_nodos_en_tres(INDICE*, int nodo_izq, int nodo_der, int padre, B_NodoEntry nuevo_entry);
48 static EMUFS_REG_ID b_insertar_dup_en_pos(INDICE *idx, INDICE_DATO pos, INDICE_DATO nuevo);
50 static void abreviar_claves(INDICE *idx, B_NodoEntry *array, B_NodoHeader *header);
51 static void desabreviar_claves(INDICE *idx, B_NodoEntry *array, B_NodoHeader *header);
52 int b_borrar_dup_clave(INDICE *idx, INDICE_DATO k, INDICE_DATO dato);
54 void emufs_indice_b_crear(INDICE *idx)
63 header.hijo_izquierdo = -1;
65 fp = fopen(idx->filename, "w");
67 PERR("Error al crear el archivo");
71 /* Creo el archivo con el Nodo raiz */
72 bloque = (char *)malloc(idx->tam_bloque);
73 memset(bloque, -1, idx->tam_bloque);
75 memcpy(bloque, &header, sizeof(B_NodoHeader));
77 fwrite(bloque, idx->tam_bloque, 1, fp);
81 int emufs_indice_b_insertar(INDICE *idx, CLAVE clave, INDICE_DATO dato)
83 int i, nodo_id, padre_id;
90 nodo = b_leer_nodo(idx, 0);
91 padre_id = nodo_id = 0;
94 if (padre) free(padre);
97 b_leer_header(nodo, &header);
98 claves = b_leer_claves(nodo, &header);
100 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) i++;
101 if ((i<header.cant) && (emufs_indice_es_igual(idx, claves[i].clave, clave))) {
102 if (idx->funcion == IND_PRIMARIO) {
103 PERR("Indice primario no puede contener claves duplicadas!");
108 b_insertar_dup_en_pos(idx, claves[i].dato, dato);
110 if (idx->tipo_dato == IDX_STRING) {
111 /* Tengo que sacar el texto repetido del archivo de textos */
112 idx->emu_string->borrar_registro(idx->emu_string, clave, dummy);
117 nodo = b_leer_nodo(idx, header.hijo_izquierdo);
118 nodo_id = header.hijo_izquierdo;
120 nodo = b_leer_nodo(idx, claves[i-1].hijo_derecho);
121 nodo_id = claves[i-1].hijo_derecho;
126 if (nodo) free(nodo);
130 if (idx->funcion != IND_PRIMARIO) {
131 /* Agrego el DATO real al archivo de claves repetiras
132 * y me guardo el ID para poner en el indice
135 dato.id = b_insertar_dup_en_pos(idx, dummy, dato);
138 b_insertar_en_nodo(idx, clave, dato, nodo_id, nodo, -1, -1);
139 return 1; /* Agregar OK! */
142 INDICE_DATO emufs_indice_b_buscar(INDICE *idx, CLAVE clave)
152 nodo = b_leer_nodo(idx, 0);
155 b_leer_header(nodo, &header);
156 claves = b_leer_claves(nodo, &header);
158 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) i++;
159 if ((i<header.cant) && (emufs_indice_es_igual(idx, claves[i].clave, clave))) {
160 ret = claves[i].dato;
161 b_grabar_nodo(idx, nodo_id, nodo);
166 b_grabar_nodo(idx, nodo_id, nodo);
168 nodo = b_leer_nodo(idx, header.hijo_izquierdo);
169 nodo_id = header.hijo_izquierdo;
171 nodo = b_leer_nodo(idx, claves[i-1].hijo_derecho);
172 nodo_id = claves[i-1].hijo_derecho;
178 /* Nodo no encontrado */
179 ret.id = ret.bloque = -1;
183 int emufs_indice_b_borrar(INDICE *idx, CLAVE k, INDICE_DATO dato)
185 /* Busco el nodo que contiene la clave,si es que esta existe */
192 nodo_id = 0; /* Tomo la raiz */
193 nodo = b_leer_nodo(idx, nodo_id);
194 while (nodo && !encontrado) {
195 /* Obtengo los datos del nodo */
196 b_leer_header(nodo, &header);
197 claves = b_leer_claves(nodo, &header);
200 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, k))) i++;
202 if ((emufs_indice_es_igual(idx, claves[i].clave, k)) && (i<header.cant))
207 nodo_id = header.hijo_izquierdo;
208 nodo = b_leer_nodo(idx, nodo_id);
210 nodo_id = claves[i-1].hijo_derecho;
212 nodo = b_leer_nodo(idx, nodo_id);
218 PERR("Clave encontrada, borrando ...");
219 fprintf(stderr, "%s: La clave a borrar esta en el nodo %d\n", idx->nombre, nodo_id);
220 if (idx->funcion != IND_PRIMARIO) {
221 /* Debo borrar primero la clave desde el archivo de
222 * claves repetidas, y si recien ahi me quedo sin claves,
223 * borrar la clave del arbol
225 PERR("Vamos a borrar duplicados");
226 encontrado = b_borrar_dup_clave(idx, claves[i].dato, dato);
227 fprintf(stderr, "Listo, encontrado = %d\n", encontrado);
230 b_borrar_clave(idx, nodo, nodo_id, k);
233 PERR("Clave no encontrada");
238 static int b_ultimo_id(INDICE *idx)
242 fp = fopen(idx->filename, "r");
243 fseek(fp, 0, SEEK_END);
244 i = ftell(fp)/idx->tam_bloque;
250 static char *b_crear_nodo(INDICE *idx, int *id)
255 (*id) = b_ultimo_id(idx);
259 header.hijo_izquierdo = -1;
262 bloque = (char *)malloc(idx->tam_bloque);
263 memset(bloque, -1, idx->tam_bloque);
264 memcpy(bloque, &header, sizeof(B_NodoHeader));
266 b_grabar_nodo(idx, *id, bloque);
271 char *b_leer_nodo(INDICE *idx, int id)
275 /*B_NodoHeader header;
276 B_NodoEntry *claves;*/
278 if (id < 0) return NULL;
280 fp = fopen(idx->filename, "r");
281 if (fp == NULL) return NULL;
283 fseek(fp, id*idx->tam_bloque, SEEK_SET);
285 out = (char *)malloc(idx->tam_bloque);
291 if (fread(out, 1, idx->tam_bloque, fp) != idx->tam_bloque) {
293 /* No se puso leer el nodo */
298 /* Si estoy manejando string tengo que sacar las abreviaturas */
299 /* if (idx->tipo_dato == IDX_STRING) {
300 b_leer_header(out, &header);
301 claves = b_leer_claves(out, &header);
302 desabreviar_claves(idx, claves, &header);
308 static void b_grabar_nodo(INDICE *idx, int id, char *data)
311 /*B_NodoHeader header;
312 B_NodoEntry *claves;*/
314 /* Si las claves son de tipo string debo abreviar antes de guardar */
315 /* if (idx->tipo_dato == IDX_STRING) {
316 b_leer_header(data, &header);
317 claves = b_leer_claves(data, &header);
318 abreviar_claves(idx, claves, &header);
320 fp = fopen(idx->filename, "r+");
321 fseek(fp, id*idx->tam_bloque, SEEK_SET);
322 fwrite(data, 1, idx->tam_bloque, fp);
326 void b_leer_header(char *src, B_NodoHeader *header)
330 memcpy(header, src, sizeof(B_NodoHeader));
333 static void b_actualizar_header(char *src, B_NodoHeader *header)
336 memcpy(src, header, sizeof(B_NodoHeader));
339 B_NodoEntry *b_leer_claves(char *src, B_NodoHeader *header)
341 return (B_NodoEntry *)(src+sizeof(B_NodoHeader));
344 static void b_insertar_en_nodo(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo1, int hijo2)
351 B_NodoHeader nodo_header, nuevo_header;
352 B_NodoEntry *claves, *tmp_claves, *claves_nuevo;
357 nodo = b_crear_nodo(idx, &nodo_id);
359 b_leer_header(nodo, &nodo_header);
360 claves = b_leer_claves(nodo, &nodo_header);
362 padre = b_leer_nodo(idx, nodo_header.padre);
364 if (nodo_header.cant == CANT_HIJOS(idx)) {
367 * TODO FIXME XXX TODO FIXME XXX TODO FIXME XXX
369 *******************************************************
370 * Pseudocódigo que explica que hay que hacer si es B*
372 * OJO! Si el nodo en el cual estoy insertando es el
373 * raíz, se maneja exactamente igual que en el B común,
374 * así que el if sería algo como:
375 * if (idx->tipo == IND_B_ASC && !es_raiz(nodo_id))
376 *******************************************************
378 * nuevo_entry = new entry(clave, dato, hijo_der)
379 * padre = get_padre(nodo)
381 * // Veo si puedo pasar a derecha
382 * hijo_derecho = get_hijo_derecho(padre)
383 * if (hijo_derecho != NULL && hijo_derecho.cantidad_entries < MAX_ENTRIES)
384 * buffer = new entries[MAX_ENTRIES+1]
385 * copiar_entries(buffer, nodo)
386 * insertar_ordenado(buffer, nuevo_entry)
387 * entry_a_pasar = get_entry_extremo_derecho(buffer)
388 * b_pasar_clave_a_derecha(idx, hijo_derecho, hijo_derecho.id, padre, padre.id, padre.posicion, entry_a_pasar)
391 * // Veo si puedo pasar a izquierda
392 * hijo_izquierdo = get_hijo_izquierdo(padre)
393 * if (hijo_izquierdo != NULL && hijo_izquierdo.cantidad_entries < MAX_ENTRIES)
394 * buffer = new entries[MAX_ENTRIES+1]
395 * copiar_entries(buffer, nodo)
396 * insertar_ordenado(buffer, nuevo_entry)
397 * entry_a_pasar = get_entry_extremo_izquierdo(buffer)
398 * b_pasar_clave_a_izquierda(idx, hijo_izquierdo, hijo_izquierdo.id, padre, padre.id, padre.posicion, entry_a_pasar)
401 * // Parto 2 nodos en 3.
402 * if (hijo_izquierdo != NULL)
403 * b_partir_dos_nodos_en_tres(idx, hijo_izquierdo, nodo, padre, nuevo_entry)
404 * else // Siempre alguno tiene que existir.
405 * b_partir_dos_nodos_en_tres(idx, nodo, hijo_derecho, padre, nuevo_entry)
409 **********************************************************************************
410 * Fin de pseudocódigo, si no es B* se sigue haciendo lo que dice a continuación. *
411 **********************************************************************************
413 nuevo = b_crear_nodo(idx, &nuevo_id);
415 /* Creo una lista ordenada de los nodos a partir */
416 tmp_claves = (B_NodoEntry *)malloc(sizeof(B_NodoEntry)*(nodo_header.cant+1));
417 total = nodo_header.cant+1;
418 while ((i<nodo_header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) {
419 tmp_claves[i] = claves[i];
422 tmp_claves[i].clave = clave;
423 tmp_claves[i].dato = dato;
424 /*tmp_claves[i].hijo_derecho = hijo1;*/
426 nodo_header.hijo_izquierdo = hijo1;
427 tmp_claves[i].hijo_derecho = hijo2;
429 tmp_claves[i-1].hijo_derecho = hijo1;
430 tmp_claves[i].hijo_derecho = hijo2;
432 while (i < nodo_header.cant) {
433 tmp_claves[i+1] = claves[i];
437 /* Asigno a cada nodo lo que corresponde */
438 b_leer_header(nuevo, &nuevo_header);
440 nuevo_header.nivel = nodo_header.nivel;
441 nodo_header.cant = total/2;
442 nuevo_header.cant = (total-1) - nodo_header.cant;
444 memset(claves, '*', idx->tam_bloque-sizeof(B_NodoHeader));
445 for(j=0; j<nodo_header.cant; j++)
446 claves[j] = tmp_claves[j];
448 claves_nuevo = b_leer_claves(nuevo, &nuevo_header);
449 memset(claves_nuevo, '*', idx->tam_bloque-sizeof(B_NodoHeader));
450 for(j=0; j<nuevo_header.cant; j++)
451 claves_nuevo[j] = tmp_claves[j+total/2+1];
453 b_actualizar_header(nodo, &nodo_header);
454 b_actualizar_header(nuevo, &nuevo_header);
457 clave = tmp_claves[total/2].clave;
458 dato = tmp_claves[total/2].dato;
460 b_grabar_nodo(idx, nodo_id, nodo);
461 b_grabar_nodo(idx, nuevo_id, nuevo);
469 fprintf(stderr, "Nodos espliteados = %d %d\n", hijo1, hijo2);
471 nodo_id = nodo_header.padre;
473 /* Oops, parti el raiz, y este debe quedar en 0, lo paso a otro bloque
474 * y dejo el padre vacio
476 char *tmp_nuevo = b_crear_nodo(idx, &nodo_id);
477 memcpy(tmp_nuevo, nodo, idx->tam_bloque);
481 clave = tmp_claves[total/2].clave;
482 dato = tmp_claves[total/2].dato;
484 b_grabar_nodo(idx, nuevo_id+1, nodo);
485 b_grabar_nodo(idx, nuevo_id, nuevo);
494 fprintf(stderr, "Nodos espliteados = %d %d\n", hijo1, hijo2);
495 /* Limpio al padre */
496 nuevo = b_leer_nodo(idx, 0);
498 b_leer_header(nuevo, &nuevo_header);
499 nuevo_header.cant = 0;
500 nuevo_header.padre = -1;
501 nuevo_header.nivel = nodo_header.nivel+1;
502 nuevo_header.hijo_izquierdo = -1;
503 fprintf(stderr, "root.nivel=%d\n", nuevo_header.nivel);
504 memset(nuevo, -1, idx->tam_bloque);
505 b_actualizar_header(nuevo, &nuevo_header);
506 b_grabar_nodo(idx, 0, nuevo);
513 /* La clave entra en este nodo!! */
514 b_insertar_en_nodo_con_lugar(idx, clave, dato, nodo_id, nodo, hijo1, hijo2);
520 void b_insertar_en_nodo_con_lugar(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo_izq, int hijo_der)
523 B_NodoHeader nodo_header;
525 b_leer_header(nodo, &nodo_header);
526 claves = b_leer_claves(nodo, &nodo_header);
527 if (nodo_header.cant > 0) {
529 while ((i < nodo_header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) i++;
530 for(j=nodo_header.cant; j > i; j--)
531 claves[j] = claves[j-1];
534 claves[i].clave = clave;
535 claves[i].dato = dato;
537 nodo_header.hijo_izquierdo = hijo_izq;
538 claves[i].hijo_derecho = hijo_der;
540 claves[i-1].hijo_derecho = hijo_izq;
541 claves[i].hijo_derecho = hijo_der;
544 b_actualizar_header(nodo, &nodo_header);
545 b_grabar_nodo(idx, nodo_id, nodo);
547 /* Debo actualizar los punteros al padre de los hijos */
548 if (hijo_izq != -1) {
549 char* nuevo = b_leer_nodo(idx, hijo_izq);
551 B_NodoHeader nuevo_header;
552 fprintf(stderr, "Actualizo padre de %d a %d\n", hijo_izq, nodo_id);
553 b_leer_header(nuevo, &nuevo_header);
554 nuevo_header.padre = nodo_id;
555 b_actualizar_header(nuevo, &nuevo_header);
556 b_grabar_nodo(idx, hijo_izq, nuevo);
558 } else printf("FUCK! hijo_izq=%d no existe!\n", hijo_izq);
560 if (hijo_der != -1) {
561 char* nuevo = b_leer_nodo(idx, hijo_der);
563 B_NodoHeader nuevo_header;
564 fprintf(stderr, "Actualizo padre de %d a %d\n", hijo_der, nodo_id);
565 b_leer_header(nuevo, &nuevo_header);
566 nuevo_header.padre = nodo_id;
567 b_actualizar_header(nuevo, &nuevo_header);
568 b_grabar_nodo(idx, hijo_der, nuevo);
570 } else printf("FUCK! hijo_der=%d no existe!\n", hijo_der);
574 void b_insertar_en_nodo_con_lugar_sin_hijo_izq(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo_der)
577 B_NodoHeader nodo_header;
579 b_leer_header(nodo, &nodo_header);
580 claves = b_leer_claves(nodo, &nodo_header);
581 if (nodo_header.cant > 0) {
583 while ((i < nodo_header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) i++;
584 for(j=nodo_header.cant; j > i; j--)
585 claves[j] = claves[j-1];
588 claves[i].clave = clave;
589 claves[i].dato = dato;
590 claves[i].hijo_derecho = hijo_der;
592 b_actualizar_header(nodo, &nodo_header);
593 b_grabar_nodo(idx, nodo_id, nodo);
595 /* Debo actualizar el puntero al padre del hijo */
596 if (hijo_der != -1) {
597 char* nuevo = b_leer_nodo(idx, hijo_der);
599 B_NodoHeader nuevo_header;
600 b_leer_header(nuevo, &nuevo_header);
601 nuevo_header.padre = nodo_id;
602 b_actualizar_header(nuevo, &nuevo_header);
603 b_grabar_nodo(idx, hijo_der, nuevo);
605 } else printf("FUCK! hijo_der=%d no existe!\n", hijo_der);
609 INDICE_DATO *emufs_indice_b_buscar_muchos(INDICE *idx, CLAVE clave, int *cant)
615 INDICE_DATO dato, *ret;
617 /* Si el indice es primario no tiene sentido hacer nada */
618 if (idx->funcion == IND_PRIMARIO) {
620 PERR("INDICE PRIMARIO NO SOPORTA BUSQUEDA MULTIPLE");
624 /* Busco la clave en el arbol */
625 dato = emufs_indice_b_buscar(idx, clave);
628 PERR("CLAvE NO ENCONTRADA EN EL ARBOL!");
631 /* Leo el contenido actual */
634 leido = (char *)idx->emu_mult->leer_registro(idx->emu_mult, k, &tam, &error);
636 /* Incremento en 1 la cantidad */
638 (*cant) = *((int *)leido);
642 ret = malloc(sizeof(INDICE_DATO)*(*cant));
643 memcpy(ret, leido+sizeof(int), (*cant)*sizeof(INDICE_DATO));
648 static void b_borrar_clave(INDICE *idx, char *nodo, int nodo_id, CLAVE k)
650 int pos, actual_id, padre_id, i, pos_padre, izquierda_id, derecha_id, p;
651 B_NodoHeader header, header_actual, header_padre, header_izq, header_der;
652 B_NodoEntry *claves, *claves_actual, *claves_padre;/*, *claves_izq, *claves_der;*/
653 char *actual, *padre, *izq, *der;
655 PERR("Borrando clave");
656 b_leer_header(nodo, &header);
657 claves = b_leer_claves(nodo, &header);
660 /* Busco la posicion dentro de la lista de claves */
661 PERR("Buscando lugar donde se encuentra la clave");
662 while (emufs_indice_es_menor(idx, claves[pos].clave, k)) pos++;
664 /* Es el nodo una hoja? */
665 fprintf(stderr, "La clave esta en la pos = %d\n", pos);
666 if (header.hijo_izquierdo != -1) {
667 PERR("Nodo no es hoja, intercambio");
668 actual = b_leer_nodo(idx, claves[pos].hijo_derecho);
669 actual_id = claves[pos].hijo_derecho;
670 p = claves[pos].hijo_derecho;
672 b_leer_header(actual, &header_actual);
673 while (header_actual.hijo_izquierdo != -1) {
674 actual_id = header_actual.hijo_izquierdo;
676 actual = b_leer_nodo(idx, actual_id);
677 b_leer_header(actual, &header_actual);
679 claves_actual = b_leer_claves(actual, &header_actual);
681 claves[pos] = claves_actual[0];
682 claves[pos].hijo_derecho = p;
684 b_grabar_nodo(idx, nodo_id, nodo);
687 PERR("Nodo es hoja");
689 header_actual = header;
690 claves_actual = claves;
695 PERR("Borrando clave");
696 for(i=pos; i < header_actual.cant-1; i++) {
697 claves_actual[i] = claves_actual[i+1];
699 PERR("Borrado completo");
700 header_actual.cant--;
701 /* Guardo los cambios */
702 b_actualizar_header(actual, &header_actual);
703 b_grabar_nodo(idx, actual_id, actual);
705 /* Se cumple la condicion de hijos? */
706 PERR("Dejo todo consistente");
707 fprintf(stderr, "Condicion : %d >= %d\n", header_actual.cant, MIN_HIJOS(idx));
708 if ((header_actual.cant >= MIN_HIJOS(idx)) || (actual_id == 0)) {
709 PERR("Borrar completo sin fundir");
713 PERR("Node queda con menos hijos de los posibles!");
714 /* Tengo que pasar datos o fundir nodos :-( */
716 padre_id = header.padre;
717 if (padre_id == -1) continue;
718 padre = b_leer_nodo(idx, padre_id);
719 b_leer_header(padre, &header_padre);
720 claves_padre = b_leer_claves(padre, &header_padre);
721 fprintf(stderr, "ID del padre = %d de nivel %d\n", padre_id, header_padre.nivel);
722 /* TODO Tengo el hijo_izquierdo para revisar!! XXX */
723 if (header_padre.hijo_izquierdo == actual_id) {
724 PERR("Soy el hijo izquierdo de padre");
725 izquierda_id = -1; /* No tengo hermano izquierdo */
726 /* Mi hermano derecho es el primer nodo del padre */
727 derecha_id = claves_padre[0].hijo_derecho;
728 der = b_leer_nodo(idx, derecha_id);
729 b_leer_header(der, &header_der);
732 PERR("Buscando que hijo soy");
733 for(pos_padre=0; (claves_padre[pos_padre].hijo_derecho != actual_id); pos_padre++) { }
735 if (pos_padre == header_padre.cant) {
736 PERR("ERROR GRAVE. Padre no me contiene :-(");
739 /* Busco mis hermanos a derecha e izquierda, si es que existen */
740 PERR("Ya me encontre, busco a mis hermanos");
741 if (pos_padre >= 0) {
743 izquierda_id = header_padre.hijo_izquierdo;
745 izquierda_id = claves_padre[pos_padre-1].hijo_derecho;
746 izq = b_leer_nodo(idx, izquierda_id);
747 b_leer_header(izq, &header_izq);
751 if (pos_padre < header_padre.cant) {
752 derecha_id = claves_padre[pos_padre+1].hijo_derecho;
753 der = b_leer_nodo(idx, derecha_id);
754 b_leer_header(der, &header_der);
759 /* Intendo pasar una clave desde un hermano hacia mi */
760 PERR("Ta calcule lo que tengo que hacer");
761 if ((derecha_id != -1) && (header_der.cant > MIN_HIJOS(idx))) {
762 PERR("Le pido clave a derecha");
763 fprintf(stderr, "ANTES DE PEDIR DERECHA TENGO %d claves\n", header_actual.cant);
764 fprintf(stderr, "PEDIR DERECHA DATOS : yo=%d, padre=%d, der=%d, pos_clave=%d\n", actual_id, padre_id, derecha_id, pos_padre);
765 b_pedir_clave_derecha(der, derecha_id, padre, padre_id, actual, actual_id, pos_padre);
767 b_leer_header(der, &header_der);
768 b_leer_header(padre, &header_padre);
769 b_leer_header(actual, &header_actual);
770 fprintf(stderr, "DESPUES DE PEDIR DERECHA TENGO %d claves\n", header_actual.cant);
771 } else if ((izquierda_id != -1) && (header_izq.cant > MIN_HIJOS(idx))) {
772 PERR("Le pido clave a izquierda");
773 b_pedir_clave_izquierda(izq, izquierda_id, padre, padre_id, actual, actual_id, pos_padre);
774 /* como se modificaron cosas, leo de nuevo los headers */
775 b_leer_header(izq, &header_izq);
776 b_leer_header(padre, &header_padre);
777 b_leer_header(actual, &header_actual);
780 /* No pude pasar clave, tengo que fundir :-( */
781 PERR("Fundo nodos!");
782 if (derecha_id != -1) {
783 b_fundir_nodo(idx, actual, actual_id, padre, padre_id, der, derecha_id, pos_padre);
785 b_fundir_nodo(idx, izq, izquierda_id, padre, padre_id, actual, actual_id, pos_padre);
789 /* TODO que guardo ?, todo ? */
790 b_grabar_nodo(idx, actual_id, actual);
791 if (izquierda_id != -1) b_grabar_nodo(idx, izquierda_id, izq);
792 if (derecha_id != -1) b_grabar_nodo(idx, derecha_id, der);
793 if (padre_id != -1) b_grabar_nodo(idx, padre_id, padre);
794 if (actual_id != -1) free(actual);
795 if (derecha_id != -1) free(der);
796 if (izquierda_id != -1) free(izq);
798 actual_id = padre_id;
799 b_leer_header(actual, &header_actual);
800 claves_actual = b_leer_claves(actual, &header_actual);
801 } while ((actual_id != -1) && (actual_id != 0) && (header_actual.cant < MIN_HIJOS(idx)));
804 static void b_pedir_clave_derecha(char *der, int der_id, char *padre, int padre_id, char *nodo, int nodo_id, int pos_clave)
807 B_NodoHeader h_der, h_padre, h_nodo;
808 B_NodoEntry *c_der, *c_padre, *c_nodo;
811 b_leer_header(nodo, &h_nodo);
812 c_nodo = b_leer_claves(nodo, &h_nodo);
813 b_leer_header(der, &h_der);
814 c_der = b_leer_claves(der, &h_der);
815 b_leer_header(padre, &h_padre);
816 c_padre = b_leer_claves(padre, &h_padre);
819 c_nodo[h_nodo.cant] = c_padre[pos_clave+1];
820 c_nodo[h_nodo.cant].hijo_derecho = -1; /* XXX */
823 c_padre[pos_clave+1] = c_der[0];
824 c_padre[pos_clave+1].hijo_derecho = der_id;
826 /* Muevo las claves de derecho */
828 for(i=0; i<h_der.cant-1; i++) {
829 c_der[i] = c_der[i+1];
834 b_actualizar_header(der, &h_der);
835 b_actualizar_header(nodo, &h_nodo);
839 void b_pasar_clave_a_derecha(INDICE *idx, char *der, int der_id, char *padre, int padre_id, int padre_pos, B_NodoEntry entry)
841 B_NodoHeader padre_h, der_h;
842 B_NodoEntry* padre_entries;
843 /* Leo claves y cabecera del nodo de la derecha y del padre */
844 b_leer_header(padre, &padre_h);
845 b_leer_header(der, &der_h);
846 padre_entries = b_leer_claves(padre, &padre_h);
847 /* Inserto en el hijo derecho la clave del padre */
848 b_insertar_en_nodo_con_lugar(idx, padre_entries[padre_pos].clave, padre_entries[padre_pos].dato,
849 der_id, der, entry.hijo_derecho, der_h.hijo_izquierdo);
850 /* Reemplazo clave del padre por clave nueva */
851 entry.hijo_derecho = der_id;
852 padre_entries[padre_pos] = entry;
855 void b_pedir_clave_izquierda(char *izq, int izq_id, char *padre, int padre_id, char *nodo, int nodo_id, int pos_clave)
858 B_NodoHeader h_izq, h_padre, h_nodo;
859 B_NodoEntry *c_izq, *c_padre, *c_nodo;
861 b_leer_header(nodo, &h_nodo);
862 c_nodo = b_leer_claves(nodo, &h_nodo);
863 b_leer_header(izq, &h_izq);
864 c_izq = b_leer_claves(izq, &h_izq);
865 b_leer_header(padre, &h_padre);
866 c_padre = b_leer_claves(padre, &h_padre);
868 PERR("Muevo las claves");
869 for(i=h_nodo.cant; i>0;i--)
870 c_nodo[i] = c_nodo[i-1];
873 PERR("Paso clave de padre a nodo");
874 c_nodo[0] = c_padre[pos_clave];
875 c_nodo[0].hijo_derecho = -1; /* XXX */
876 PERR("Paso clave de izquierda a padre");
877 c_padre[pos_clave] = c_izq[h_izq.cant-1];
878 c_padre[pos_clave].hijo_derecho = nodo_id;
882 b_actualizar_header(izq, &h_izq);
883 b_actualizar_header(padre, &h_padre);
884 b_actualizar_header(nodo, &h_nodo);
888 void b_pasar_clave_a_izquierda(INDICE* idx, char *izq, int izq_id, char *padre, int padre_id, int padre_pos, B_NodoEntry entry, int id_entry_hijo_izq, int id_entry_nodo)
890 B_NodoHeader padre_h;
891 B_NodoEntry* padre_entries;
892 /* Leo claves y cabecera del nodo de la izquierda y del padre */
893 b_leer_header(padre, &padre_h);
894 padre_entries = b_leer_claves(padre, &padre_h);
895 /* Inserto en el hijo izquirdo la clave del padre */
896 b_insertar_en_nodo_con_lugar_sin_hijo_izq(idx, padre_entries[padre_pos].clave, padre_entries[padre_pos].dato,
897 izq_id, izq, id_entry_hijo_izq);
898 /* Reemplazo clave del padre por clave nueva */
899 entry.hijo_derecho = id_entry_nodo;
900 padre_entries[padre_pos] = entry;
903 static void b_fundir_nodo(INDICE *idx, char *izq, int izq_id, char *padre, int padre_id, char *der, int der_id, int pos_padre)
906 B_NodoHeader h_izq, h_padre, h_der;
907 B_NodoEntry *c_izq, *c_padre, *c_der;
909 b_leer_header(der, &h_der);
910 c_der = b_leer_claves(der, &h_der);
911 b_leer_header(izq, &h_izq);
912 c_izq = b_leer_claves(izq, &h_izq);
913 b_leer_header(padre, &h_padre);
914 c_padre = b_leer_claves(padre, &h_padre);
916 c_izq[h_izq.cant] = c_padre[pos_padre];
918 for(i=pos_padre; i<h_padre.cant; i++)
919 c_padre[i] = c_padre[i+1];
921 for(i=0; i<h_der.cant; i++)
922 c_izq[h_izq.cant+i] = c_der[i];
924 h_izq.cant += h_der.cant;
926 b_actualizar_header(izq, &h_izq);
927 b_actualizar_header(padre, &h_padre);
929 /* TODO Aca queda libre el nodo der, ver de recuperar! */
930 memset(der, 'X', idx->tam_bloque);
931 b_grabar_nodo(idx, der_id, der);
934 static EMUFS_REG_ID b_insertar_dup_en_pos(INDICE *idx, INDICE_DATO pos, INDICE_DATO nuevo)
943 /* Leo el contenido actual */
946 leido = (char *)idx->emu_mult->leer_registro(idx->emu_mult, k, &tam, &error);
948 /* Incremento en 1 la cantidad */
950 cant = *((int *)leido);
955 /* Obtengo un nuevo lugar para el dato nuevo */
956 /* Aca todo bien, si leido es NULL se compota como malloc */
957 leido = realloc(leido, cant*sizeof(INDICE_DATO)+sizeof(int));
958 array = (INDICE_DATO *)(leido+sizeof(int));
960 /* Pongo el dato nuevo */
961 array[cant-1] = nuevo;
963 /* Actualizo la cantidad */
964 (*((int *)leido)) = cant;
967 if (k.i_clave == -1) {
970 k.i_clave = idx->emu_mult->grabar_registro(idx->emu_mult,
972 cant*sizeof(INDICE_DATO)+sizeof(int),
975 if (k.i_clave == -1) PERR("ALGO NO GRABO BIEN!!");
977 /* Modifico el que ya existia! */
980 idx->emu_mult->modificar_registro(idx->emu_mult,
983 cant*sizeof(INDICE_DATO)+sizeof(int),
993 char *abreviar(char *primera, char *actual, int *iguales)
996 while (((*primera) != '\0') && ((*actual) != '\0')) {
997 if ((*primera) == (*actual)) {
1002 /* No coinciden mas! */
1010 static void abreviar_claves(INDICE *idx, B_NodoEntry *array, B_NodoHeader *header)
1012 char *primera, *actual, *resto, salvar[100];
1013 EMUFS_REG_SIZE size;
1017 /* Agarro la primer clave entera como referencia */
1018 primera = (char *)idx->emu_string->leer_registro(idx->emu_string, array[0].clave, &size, &error);
1019 for(i=1; i<header->cant; i++) {
1020 actual = (char *)idx->emu_string->leer_registro(idx->emu_string, array[i].clave, &size, &error);
1021 if (*actual == '*') {
1025 resto = abreviar(primera, actual, &iguales);
1026 /* Para que tenga sentido abreviar tengo que tener
1027 * mas de 2 letras iguales, si no no gano nada y complica las cosas
1031 sprintf(salvar, "%d|%s", iguales, resto);
1034 idx->emu_string->modificar_registro(idx->emu_string, array[i].clave, salvar, strlen(salvar)+1, &error, dummy1);
1044 static void desabreviar_claves(INDICE *idx, B_NodoEntry *array, B_NodoHeader *header)
1046 char *primera, *actual, *resto, salvar[100];
1047 EMUFS_REG_SIZE size;
1051 /* Agarro la primer clave entera como referencia */
1052 primera = (char *)idx->emu_string->leer_registro(idx->emu_string, array[0].clave, &size, &error);
1053 for(i=1; i<header->cant; i++) {
1054 actual = (char *)idx->emu_string->leer_registro(idx->emu_string, array[i].clave, &size, &error);
1055 if (*actual == '*') {
1059 iguales = strtol(actual, &resto, 10);
1060 if ((iguales > 0) && (*resto == '|')) {
1062 strncpy(salvar, primera, iguales);
1063 salvar[iguales] = '\0';
1064 strcat(salvar, resto+1); /* +1 para saltar el separador */
1065 idx->emu_string->modificar_registro(idx->emu_string, array[i].clave, salvar, strlen(salvar)+1, &error, dummy2);
1076 static void b_partir_dos_nodos_en_tres(INDICE* idx, int nodo_izq, int nodo_der, int padre, B_NodoEntry nuevo_entry)
1079 * PSEUDOCODIGO TODO FIXME XXX TODO FIXME XXX TODO FIXME XXX
1081 * // Creo un buffer con todos los entries (las claves) de ambos nodos, mas el padre y la nueva, ordenadas
1082 * buffer_size = 2*MAX_ENTRIES+2
1083 * buffer = new entries[buffer_size]
1084 * copiar_entries(buffer, nodo_izq)
1085 * concatenar_entries(buffer, padre)
1086 * concatenar_entries(buffer, nodo_der)
1087 * insertar_ordenado(buffer, nuevo_entry)
1088 * // Borro los 2 nodos viejos para reutilizarlos y creo el tercero
1089 * borrar_entries(nodo_izq)
1090 * borrar_entries(nodo_der)
1091 * nodo_nuevo = new nodo()
1092 * // Copio de a tercios del buffer en los nuevos nodos, excluyendo las 2 claves 'limítrofes' para insertarlas luego en el padre
1093 * copiar_algunos_entries(nodo_izq, buffer, 0, (buffer_size/3)-1)
1094 * entry_promovido1 = buffer[buffer_size/3]
1095 * copiar_algunos_entries(nodo_izq, buffer, (buffer_size/3)+1, 2*(buffer_size/3))
1096 * entry_promovido2 = buffer[(2*(buffer_size/3))+1]
1097 * copiar_algunos_entries(nodo_nuevo, buffer, (2*(buffer_size/3))+2, buffer_size-1))
1098 * // Finalmente inserto (recursivamente, porque esta funcion es llamada desde b_insertar_en_nodo()) las claves promovidas en el padre
1099 * b_insertar_en_nodo(idx, entry_promovido.clave, entry_promovido.dato, entry_promovido.id, entry_promovido, nodo_izq.id, nodo_der.id)
1100 * b_insertar_en_nodo(idx, entry_promovido.clave, entry_promovido.dato, entry_promovido.id, entry_promovido, nodo_der.id, nodo_nuevo.id)
1105 CLAVE emufs_indice_b_obtener_menor_clave(INDICE *idx)
1107 B_NodoHeader header;
1108 B_NodoEntry *claves;
1112 nodo = b_leer_nodo(idx, 0);
1113 b_leer_header(nodo, &header);
1114 /* Tengo que ir siempre a la izquierda hasta una hora */
1115 while (header.hijo_izquierdo != -1) {
1117 nodo = b_leer_nodo(idx, header.hijo_izquierdo);
1118 b_leer_header(nodo, &header);
1121 /* Listo, ahora solo leo la primer clave */
1122 claves = b_leer_claves(nodo, &header);
1123 k = claves[0].clave;
1128 CLAVE emufs_indice_b_obtener_mayor_clave(INDICE *idx)
1130 B_NodoHeader header;
1131 B_NodoEntry *claves;
1136 nodo = b_leer_nodo(idx, 0);
1137 b_leer_header(nodo, &header);
1138 claves = b_leer_claves(nodo, &header);
1139 /* Tengo que ir siempre a la izquierda hasta una hora */
1140 while (claves[header.cant-1].hijo_derecho != -1) {
1141 i = claves[header.cant-1].hijo_derecho;
1143 nodo = b_leer_nodo(idx, i);
1144 b_leer_header(nodo, &header);
1145 claves = b_leer_claves(nodo, &header);
1148 /* Listo, ahora solo leo la primer clave */
1149 k = claves[header.cant-1].clave;
1154 CLAVE emufs_indice_b_obtener_sig_clave(INDICE *idx, CLAVE k)
1157 B_NodoHeader header;
1158 B_NodoEntry *claves;
1163 /* Primero busco la clave pasada por parametro */
1164 nodo = b_leer_nodo(idx, 0);
1167 b_leer_header(nodo, &header);
1168 claves = b_leer_claves(nodo, &header);
1170 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, k))) i++;
1171 if ((i<header.cant) && (emufs_indice_es_igual(idx, claves[i].clave, k))) {
1172 /* LA ENCONTRE! , ahora busco la siguiente clave!! */
1173 fprintf(stderr, "Me encontre en pos %d en el padre\n", i);
1174 if ((i+1)<header.cant) {
1175 PERR("Joya, hay lugar a la derecha");
1176 if (claves[i].hijo_derecho == -1) {
1177 PERR("Y soy hoja!!");
1178 /* Joya!, fue facil, la siguiente va en camino! */
1179 salida = claves[i+1].clave;
1184 PERR("No soy hoja, busco la hoja de menor");
1185 /* Mmmmm ... la siguiente esta en uno de mis hijo */
1186 /* Necesito la mas chica de las siguientes, para eso
1187 * me voy a mi hijo derecho y de ahi bajo siempre
1188 * hacia la izquierda hacia una hoja */
1189 i = claves[i].hijo_derecho;
1191 nodo = b_leer_nodo(idx, i);
1192 b_leer_header(nodo, &header);
1193 while (header.hijo_izquierdo != -1) {
1195 nodo = b_leer_nodo(idx, header.hijo_izquierdo);
1196 b_leer_header(nodo, &header);
1198 claves = b_leer_claves(nodo, &header);
1199 salida = claves[0].clave;
1204 PERR("Fuck, tengo que ir otro nodo a buscar");
1205 /* Fuck, la siguiente clave la tengo que sacar de padre */
1206 /* Busco al mi padre, perdido en un maremoto hace mucho,muchos
1210 if (header.padre == -1) {
1211 salida.i_clave = -1;
1214 nodo = b_leer_nodo(idx, header.padre);
1215 b_leer_header(nodo, &header);
1216 claves = b_leer_claves(nodo, &header);
1218 PERR("Busco mi siguiente en mi padre");
1219 fprintf(stderr, "Padre tiene %d claves\n", header.cant);
1220 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, k))) {
1222 fprintf(stderr, "Proximo i : %d\n", i);
1224 if (i<header.cant) {
1225 PERR("Siguiente clave encontrada");
1226 salida = claves[i].clave;
1228 /* No hay mas claves! */
1229 PERR("Busque y busque pero no aparecio");
1230 salida.i_clave = -1;
1235 b_grabar_nodo(idx, nodo_id, nodo);
1237 nodo = b_leer_nodo(idx, header.hijo_izquierdo);
1238 nodo_id = header.hijo_izquierdo;
1240 nodo = b_leer_nodo(idx, claves[i-1].hijo_derecho);
1241 nodo_id = claves[i-1].hijo_derecho;
1247 /* No encontre la clave pasada, no existe */
1248 PERR("No encontre la clave pasada!!");
1249 salida.i_clave = -1;
1253 int b_borrar_dup_clave(INDICE *idx, INDICE_DATO k_dato, INDICE_DATO dato)
1263 /* Leo el contenido actual */
1265 k.i_clave = k_dato.id;
1266 leido = (char *)idx->emu_mult->leer_registro(idx->emu_mult, k, &tam, &error);
1268 if (leido == NULL) {
1269 PERR("LEI CUALQUIER COSA, BUG?");
1273 cant = *((int *)leido);
1275 /* Obtengo un nuevo lugar para el dato nuevo */
1276 array = (INDICE_DATO *)(leido+sizeof(int));
1278 /* busco pos de dato en array */
1279 for(pos=0; pos<cant; pos++) {
1280 if (array[pos].id == dato.id) break;
1283 for(i=pos; i<cant-1; i++)
1284 array[pos] = array[pos+1];
1290 /* No tengo mas cosas en esta clave, la borro */
1291 PERR("EL REGISTRO MULTIPLE QUEDO VACIO, ELIMINANDO");
1292 idx->emu_mult->borrar_registro(idx->emu_mult, k, dummy1);
1296 /* Quito el elemento */
1297 leido = realloc(leido, sizeof(int)+cant*sizeof(INDICE_DATO));
1299 /* Actualizo la cantidad */
1300 (*((int *)leido)) = cant;
1303 idx->emu_mult->modificar_registro(idx->emu_mult,
1306 cant*sizeof(INDICE_DATO)+sizeof(int),
1316 #include "indice_b_asc.c"