]> git.llucax.com Git - z.facultad/75.06/emufs.git/blobdiff - emufs/indice_b.c
paso el test, inserta una clave ordenada en un nodo
[z.facultad/75.06/emufs.git] / emufs / indice_b.c
index 5491b0d5afd957d6be202a5a0b3dcdea99d18072..4c033b60803cab8eb42bde64b1869db0a6736735 100644 (file)
@@ -1,6 +1,7 @@
 
 #include "indice_b.h"
 #include "common.h"
+#include "emufs.h"
 
 /* Cantidad de claves por nodo */
 #define CANT_HIJOS(x) ((x->tam_bloque-sizeof(B_NodoHeader))/sizeof(B_NodoEntry))
@@ -47,11 +48,13 @@ static void b_pedir_clave_derecha(char *, int, char *, int, char *, int, int);
 /** Le pide al hermano izquierdo una clave cuando se eliminan claves */
 static void b_pedir_clave_izquierda(char *, int, char *, int, char *, int, int);
 /** Le pasa al hermano derecho del nodo una clave cuando se insertan claves */
-static void b_pasar_clave_a_derecha(char *, int, char *, int, char *, int, int);
+static void b_pasar_clave_a_derecha(INDICE*, char*, int, char*, int, int, B_NodoEntry);
 /** Le pasa al hermano izquierdo una clave cuando se insertan claves */
-static void b_pasar_clave_a_izquierda(char *, int, char *, int, char *, int, int);
+static void b_pasar_clave_a_izquierda(INDICE*, char*, int, char*, int, int, B_NodoEntry);
 /** Junta 2 nodos y hace uno solo */
 static void b_fundir_nodo(char *, int, char *, int, char *, int, int);
+                       
+static EMUFS_REG_ID b_insertar_dup_en_pos(INDICE *idx, INDICE_DATO pos, INDICE_DATO nuevo);
 
 void emufs_indice_b_crear(INDICE *idx)
 {
@@ -88,6 +91,7 @@ int emufs_indice_b_insertar(INDICE *idx, CLAVE clave, INDICE_DATO dato)
        B_NodoHeader header;
        B_NodoEntry *claves;
        char *nodo, *padre;
+       INDICE_DATO dummy;
        
        /* Leo la raiz */
        nodo = b_leer_nodo(idx, 0);
@@ -102,8 +106,15 @@ int emufs_indice_b_insertar(INDICE *idx, CLAVE clave, INDICE_DATO dato)
                i=0;
                while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) i++;
                if ((i<header.cant) && (emufs_indice_es_igual(idx, claves[i].clave, clave))) {
-                       /* CLAVE DUPLICADA! */
-                       return 0;
+                       if (idx->tipo == IND_PRIMARIO) {
+                               PERR("Indice primario no puede contener claves duplicadas!");
+                               return 0;
+                       }
+                       
+                       /* TODO : Implementar carga de valor en clave duplicada! */
+                       b_insertar_dup_en_pos(idx, claves[i].dato, dato);
+                       
+                       return 1;
                } else {
                        if (i == 0) {
                                nodo = b_leer_nodo(idx, header.hijo_izquierdo);
@@ -118,6 +129,14 @@ int emufs_indice_b_insertar(INDICE *idx, CLAVE clave, INDICE_DATO dato)
        if (nodo) free(nodo);
        nodo = padre;
        nodo_id = padre_id;
+
+       if (idx->tipo != IND_PRIMARIO) {
+               /* Agrego el DATO real al archivo de claves repetiras
+                * y me guardo el ID para poner en el indice
+                */
+               dummy.id = -1;
+               dato.id = b_insertar_dup_en_pos(idx, dummy, dato);
+       }
        b_insertar_en_nodo(idx, clave, dato, nodo_id, nodo, -1, -1);
        return 1; /* Agregar OK! */
 }
@@ -130,6 +149,12 @@ INDICE_DATO emufs_indice_b_buscar(INDICE *idx, CLAVE clave)
        B_NodoEntry *claves;
        char *nodo, *tmp;
        
+       if (idx->tipo != IND_PRIMARIO) {
+               /* SOLO SE PUEDE BUSCAR CON CLAVE UNICA! */
+               ret.id = ret.bloque = -1;
+               return ret;
+       }
+       
        /* Leo la raiz */
        nodo = b_leer_nodo(idx, 0);
        while (nodo) {
@@ -667,37 +692,24 @@ static void b_pedir_clave_derecha(char *der, int der_id, char *padre, int padre_
        b_actualizar_header(nodo, &h_nodo);
 }
 
-static void b_pasar_clave_a_derecha(char *der, int der_id, char *padre, int padre_id, char *nodo, int nodo_id, int pos_clave)
+void b_pasar_clave_a_derecha(INDICE *idx, char *der, int der_id, char *padre, int padre_id, int padre_pos, B_NodoEntry entry)
 {
-/*     int i;
-       B_NodoHeader h_der, h_padre, h_nodo;
-       B_NodoEntry *c_der, *c_padre, *c_nodo;
-
-       b_leer_header(nodo, &h_nodo);
-       c_nodo = b_leer_claves(nodo, &h_nodo);
-       b_leer_header(der, &h_der);
-       c_der = b_leer_claves(der, &h_der);
-       b_leer_header(padre, &h_padre);
-       c_padre = b_leer_claves(padre, &h_padre);
-
-       c_nodo[h_nodo.cant] = c_padre[pos_clave];
-       c_nodo[h_nodo.cant].hijo_derecho = -1; / * XXX * /
-
-       c_padre[pos_clave] = c_der[0];
-       c_padre[pos_clave].hijo_derecho = der_id;
-       
-       / * Muevo las claves de derecho * /
-       for(i=0; i<h_der.cant; i++) {
-               c_der[i] = c_der[i+1];
-       }
-       h_der.cant++;
-
-       b_actualizar_header(der, &h_der);
-       b_actualizar_header(nodo, &h_nodo);
-*/
+       B_NodoHeader der_h, padre_h;
+       B_NodoEntry *der_entries, *padre_entries;
+       /* Leo claves y cabecera del nodo de la derecha y del padre */
+       b_leer_header(der, &der_h);
+       der_entries = b_leer_claves(der, &der_h);
+       b_leer_header(padre, &padre_h);
+       padre_entries = b_leer_claves(padre, &padre_h);
+       /* Inserto en el hijo derecho la clave del padre */
+       b_insertar_en_nodo_con_lugar(idx, padre_entries[padre_pos].clave, padre_entries[padre_pos].dato,
+                       der_id, der, entry.hijo_derecho, der_h.hijo_izquierdo);
+       /* Reemplazo clave del padre por clave nueva */
+       entry.hijo_derecho = der_id;
+       padre_entries[padre_pos] = entry;
 }
 
-static void b_pedir_clave_izquierda(char *izq, int izq_id, char *padre, int padre_id, char *nodo, int nodo_id, int pos_clave)
+void b_pedir_clave_izquierda(char *izq, int izq_id, char *padre, int padre_id, char *nodo, int nodo_id, int pos_clave)
 {
        int i;
        B_NodoHeader h_izq, h_padre, h_nodo;
@@ -725,7 +737,7 @@ static void b_pedir_clave_izquierda(char *izq, int izq_id, char *padre, int padr
        b_actualizar_header(nodo, &h_nodo);
 }
 
-static void b_pasar_clave_a_izquierda(char *izq, int izq_id, char *padre, int padre_id, char *nodo, int nodo_id, int pos_clave)
+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 i;
        B_NodoHeader h_izq, h_padre, h_nodo;
@@ -758,3 +770,56 @@ static void b_fundir_nodo(char *izq, int izq_id, char *padre, int padre_id, char
 {
 }
 
+static EMUFS_REG_ID b_insertar_dup_en_pos(INDICE *idx, INDICE_DATO pos, INDICE_DATO nuevo)
+{
+       int cant;
+       EMUFS_REG_SIZE tam;
+       int error;
+       INDICE_DATO *array;
+       char *leido;
+       CLAVE k;
+
+       /* Leo el contenido actual */
+       k.i_clave = pos.id;
+       leido = (char *)idx->emu_mult->leer_registro(idx->emu_mult, k, &tam, &error);
+
+       /* Incremento en 1 la cantidad */
+       if (leido != NULL)
+               cant = *((int *)leido);
+       else
+               cant = 0;
+       cant++;
+
+       /* Obtengo un nuevo lugar para el dato nuevo */
+       /* Aca todo bien, si leido es NULL se compota como malloc */
+       leido = realloc(leido, cant*sizeof(INDICE_DATO)+sizeof(int));
+       array = (INDICE_DATO *)(leido+sizeof(int));
+
+       /* Pongo el dato nuevo */
+       array[cant-1] = nuevo;
+
+       /* Actualizo la cantidad */
+       (*((int *)leido)) = cant;
+
+       /* Salvo */
+       if (k.i_clave == -1) {
+               /* Creo uno nuevo */
+               k.i_clave = idx->emu_mult->grabar_registro(idx->emu_mult,
+                                                                       leido,
+                                                                       cant*sizeof(INDICE_DATO)+sizeof(int),
+                                                                       &error
+                                                               );
+       } else {
+               /* Modifico el que ya existia! */
+               idx->emu_mult->modificar_registro(idx->emu_mult,
+                                                                       k.i_clave,
+                                                                       leido,
+                                                                       cant*sizeof(INDICE_DATO)+sizeof(int),
+                                                                       &error
+                                                               );
+       }
+       /* Clean up! */
+       free(leido);
+       return k.i_clave;
+}
+