4 /* Private prototypes */
5 /* numerando los bloques */
6 static int nuevo_bloque = -1;
7 int get_new_block_number();
8 int b_plus_grabar_nodo(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_node);
9 NODO_B_PLUS *b_plus_leer_nodo(INDEXSPECS *idx, int num_node);
10 NODO_B_PLUS *b_plus_crearnodo(INDEXSPECS *idx);
12 /** Me devuelve un numero de bloque nuevo */
13 int get_new_block_number()
19 /** Crea un nuevo nodo y lo inicializa */
20 NODO_B_PLUS *b_plus_crearnodo(INDEXSPECS *idx) {
22 NODO_B_PLUS *nodo = (NODO_B_PLUS*)malloc(sizeof(NODO_B_PLUS));
23 if (nodo == NULL) return NULL;
25 nodo->cant_claves = 0;
27 /* Calculamos lo que ocupan las cadenas de bytes claves + hijos */
28 nodo->claves = (int*)malloc(idx->size_claves);
29 nodo->hijos = (int*)malloc(idx->size_hijos);
30 memset(nodo->claves,-1,idx->size_claves);
31 memset(nodo->hijos,-1,idx->size_hijos);
36 /** Crea el archivo indice B+ */
37 int emufs_b_plus_crear(INDEXSPECS *idx) {
43 /* Creamos el archivo que contendra el indice */
44 fp = fopen(idx->filename, "w");
45 PERR("Creando indice con nodo raiz");
47 PERR("Error al crear el archivo");
52 /* Creamos el nodo raiz y lo guardamos el en indice */
53 raiz = b_plus_crearnodo(idx);
54 error = b_plus_grabar_nodo(idx,raiz,0);
56 /* Liberamos areas de memoria reservadas */
64 /* Inserta un nuevo nodo y reestructura el arbol para que quede como debe */
65 int b_plus_actualizar(NODO_B_PLUS *padre, NODO_B_PLUS *new_nodo)
70 /** Busca el nro de bloque donde se debe guardar un reg con clave X */
71 int emufs_b_plus_get_bloque(INDEXSPECS *idx, INDEX_DAT *query) {
75 /* Comienzo leyendo la raiz, entry point de toda funcion */
76 printf ("Buscando donde insertar clave: %i\n\n",query->clave.i_clave);
77 curnode = b_plus_leer_nodo(idx,0);
78 if (curnode == NULL) return -1;
79 /* Me fijo si la raiz esta vacia */
80 if ( curnode->cant_claves == 0 ){ /* entra la clave en la raiz */
81 /* ojo que este es un caso muy particular */
82 /* aumento la cant de claves*/
83 curnode->cant_claves++;
84 /* inserto la clave en el nodo, como es la primera no hace falta ordenar nada*/
85 *(curnode->claves) = query->clave.i_clave;
86 /* Debo obtener un numero de bloque para devolverle al query!!! */
87 /* por ahora el nuevo bloque se va incrementando, sin recuperacion de vacios FIX*/
88 query->num_bloque = get_new_block_number();
89 /* Le asigno al nodo del arbol el mismo numero que devolvi */
90 *(curnode->hijos) = query->num_bloque;
91 /* Cargado el query salgo de la func, luego habra que actualizar el .dat
92 y luego volver a grabar el nodo en el arbol*/
93 /*grabo el nodo en el archivo*/
94 b_plus_grabar_nodo(idx, curnode, 0);
100 /* Mientras no encontre la hoja con la clave, busco.. */
101 /* RECORDAR QUE LAS CLAVES DEBEN ESTAR ORDENADAS PARA QUE ESTO FUNCIONE !! */
102 while (curnode->nivel > 0 && curnode)
103 { /*recorro las claves hasta encontrar la primera mayor a la que quiero insertar*/
104 for(i=0; i<curnode->cant_claves; i++){
105 /* me fijo que si es mayor */
106 if ( (query->clave.i_clave > curnode->claves[i])) {
107 if ( curnode->cant_claves != i ) /* si no es la ultima clave del nodo */
108 continue; /*paso a la siguiente*/
109 else { /* si era la ultima, la clave deberia ir ahi */
110 /*cargo el proximo nodo*/
111 prox_nodo = curnode->hijos[i+1];
112 break; /*salgo del for*/
114 } else { /*si no es mayor o igual es menor*/
115 prox_nodo = curnode->hijos[i];
120 curnode = b_plus_leer_nodo(idx, prox_nodo);
123 /*cuando salgo de aca deberia tener cargado en curnode el nodo hoja que busque*/
124 for (i=0; i<curnode->cant_claves-1; i++){
125 if ( query->clave.i_clave >= curnode->claves[i] ){
126 if ( curnode->cant_claves != i ) /* si no es la ultima clave */
128 else { /* si era la ultima */
129 /* cargo en query el numero del bloque donde deberia ir la nueva clave */
130 query->num_bloque = curnode->hijos[i];
134 } else { /* si no era mayor, era menor */
135 /* guardo el bloque anterior porque me pase.. */
137 /*CREAR UN NODO NUEVO PARA METER UNA CLAVE MENOR A TODAS */
138 /* EL NUEVO NODO VA A SER UNA HOJA */
139 NODO_B_PLUS *new_nodo = b_plus_crearnodo(idx);
140 if (new_nodo == NULL){
141 PERR("NO SE PUDO CREAR EL NUEVO NODO");
144 /* aumento la cantidad de claves */
145 new_nodo->cant_claves++;
146 /* inserto la clave en el nuevo nodo (es la primera)*/
147 new_nodo->claves[0] = query->clave.i_clave;
148 /* inserto la referencia al nuevo bloque, con un n */
149 new_nodo->hijos[0] = query->num_nuevo_bloque;
150 /* no le cambio el nivel porque es hoja ( por default == 0)*/
151 /* Aca viene la papota.. hay que hacer una funcion que meta un nodo
152 * en el arbol y lo reestructure correctamente.
153 * Ademas hay que grabar el registro en el .dat*/
154 b_plus_actualizar(curnode, new_nodo); /* le mando el padre.. seguro que lo voy a necesitar */
157 query->num_bloque = curnode->hijos[i-1];
164 if (curnode) free(curnode);
168 NODO_B_PLUS *b_plus_leer_nodo(INDEXSPECS *idx, int num_node) {
172 NODO_B_PLUS *memnode = b_plus_crearnodo(idx);
173 char *disknode = (char*)malloc(idx->tam_bloque);
175 if (disknode == NULL) return NULL;
176 if (memnode == NULL) return NULL;
179 fp = fopen(idx->filename, "r+");
186 /* Intentamos leer un nodo, sino podemos error! */
187 fseek(fp, num_node*idx->tam_bloque, SEEK_SET);
188 if (fread(disknode, idx->tam_bloque, 1, fp) != 1) {
195 /* Pudimos leer un nodo de disco, ahora lo transformamos a nodo mem */
196 memcpy(memnode,disknode,SIZE_B_PLUS_HEADER);
197 memcpy(memnode->claves,disknode+SIZE_B_PLUS_HEADER,idx->size_claves);
198 memcpy(memnode->hijos,disknode+SIZE_B_PLUS_HEADER+idx->size_claves,idx->size_hijos);
201 printf("Dumping Node_%i\n",num_node);
202 printf("Nivel: %i Cant Claves: %i\n",memnode->nivel,memnode->cant_claves);
204 for (i = 0; i < idx->size_claves/sizeof(int); ++i) printf(" %i",memnode->claves[i]);
206 for (i = 0; i < idx->size_hijos/sizeof(int); ++i) printf(" %i",memnode->hijos[i]);
207 printf("\nEnd Dump\n");
213 int b_plus_grabar_nodo(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_node)
217 fp = fopen(idx->filename, "r+");
218 if (fp == NULL) return -1;
220 fseek(fp,num_node*sizeof(NODO_B_PLUS),SEEK_SET);
221 fwrite(nodo,SIZE_B_PLUS_HEADER,1,fp);
222 fwrite(nodo->claves,idx->size_claves,1,fp);
223 fwrite(nodo->hijos,idx->size_hijos,1,fp);
229 int emufs_b_plus_insertar_clave(INDEX_DAT *dataset)