]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/b_plus.c
primera parte del insertar
[z.facultad/75.06/emufs.git] / emufs / b_plus.c
1 /** Arbol B+ */
2 #include "b_plus.h"
3
4 /**#*#*#*#*#**#*#*#*#*#* Private prototypes*#*#*#*#*#**#*#*#*#*#**#*#*#*/
5 /* numerando los bloques */
6 int b_plus_grabar_nodo(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_node);
7 /*NODO_B_PLUS *b_plus_leer_nodo(INDEXSPECS *idx, int num_node);*/
8 NODO_B_PLUS *b_plus_crearnodo(INDEXSPECS *idx);
9 int b_plus_destruir_nodo(NODO_B_PLUS *nodo);
10 /*int b_plus_insertar_clave(INDEXSPECS *idx, INDEX_DAT *query);*/
11 int b_plus_insert_nonfull(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_nodo, int num_nodo_padre, CLAVE clave);
12 int b_plus_split_child(INDEXSPECS *idx,NODO_B_PLUS *new_root, int ,NODO_B_PLUS* raiz);
13 /**#*#*#*#*#**#*#*#*#*#*FIN PROTOTYPES*#*#*#*#*#**#*#*#*#*#**#*#*#*#*#*/
14
15 /** Crea un nuevo nodo y lo inicializa */
16 NODO_B_PLUS *b_plus_crearnodo(INDEXSPECS *idx) {
17         
18         NODO_B_PLUS *nodo = (NODO_B_PLUS*)malloc(sizeof(NODO_B_PLUS));
19         if (nodo == NULL) return NULL;
20         nodo->nivel = 0;
21         nodo->cant_claves = 0;
22
23     /* Calculamos lo que ocupan las cadenas de bytes claves + hijos */
24         nodo->claves = (int*)malloc(idx->size_claves);
25         nodo->hijos = (int*)malloc(idx->size_hijos);
26         memset(nodo->claves,-1,idx->size_claves);
27         memset(nodo->hijos,-1,idx->size_hijos);
28         
29     return nodo;        
30 }
31
32 /** Crea el archivo indice B+ */
33 int emufs_b_plus_crear(INDEXSPECS *idx) {
34         
35         FILE *fp;
36         NODO_B_PLUS *raiz;
37         int error = 0;
38                 
39         /* Creamos el archivo que contendra el indice */
40         fp = fopen(idx->filename, "w");
41         PERR("Creando indice con nodo raiz");
42         if (fp == NULL) {
43                 PERR("Error al crear el archivo");
44                 return -1;
45         }
46         fclose(fp);
47         
48         /* Creamos el nodo raiz y lo guardamos el en indice */
49         raiz = b_plus_crearnodo(idx);
50         error = b_plus_grabar_nodo(idx,raiz,0);
51         
52         /* Liberamos areas de memoria reservadas */
53         free(raiz->claves);
54         free(raiz->hijos);
55         free(raiz);
56         
57         return error;
58 }
59
60 /* Inserta una nueva clave y reestructura el arbol para que quede como debe */
61 int b_plus_insertar_clave(INDEXSPECS *idx, INDEX_DAT *query)
62 {
63         NODO_B_PLUS *curnode, *padre, *new_nodo;
64         int i,j, prox_nodo;
65         /* Comienzo leyendo la raiz, entry point de toda funcion */
66         curnode = b_plus_leer_nodo(idx,0);      
67         if (curnode == NULL) return -1;
68         padre = curnode;
69         while ( curnode->nivel > 0 && curnode ) {
70                 for(i=0; i<curnode->cant_claves; i++){ 
71                         /* me fijo que si es mayor */
72                         if ( (query->clave.i_clave > curnode->claves[i])) {
73                                 if ( curnode->cant_claves != i ) /* si no es la ultima clave del nodo */
74                                         continue; /*paso a la siguiente*/
75                                 else {  /* si era la ultima, la clave deberia ir ahi */
76                                         /*cargo el proximo nodo*/
77                                         prox_nodo = curnode->hijos[i+1];
78                                         break; /*salgo del for*/
79                                 }
80                         } else {  /*si no es mayor o igual es menor*/
81                                 prox_nodo = curnode->hijos[i];
82                                 break;
83                         }
84                 }
85                 padre = curnode;
86                 curnode = b_plus_leer_nodo(idx, prox_nodo);
87         } 
88         /* aca tengo el nodo donde deberia ir la clave, y su padre */ 
89         
90         if ( curnode->cant_claves < idx->size_claves/sizeof(int) ){
91                 int *claves_aux = (int*)malloc(idx->size_claves);
92                 int *hijos_aux = (int*)malloc(idx->size_hijos);
93                 memset(claves_aux,-1,idx->size_claves);
94                 memset(hijos_aux,-1,idx->size_hijos);
95                 i = 0;
96                 while ( (curnode->claves[i] < query->clave.i_clave) && (i < curnode->cant_claves)){
97                         claves_aux[i] = curnode->claves[i];
98                         hijos_aux[i] = curnode->hijos[i];
99                         i++;
100                 }
101                 curnode->cant_claves++;
102                 claves_aux[i] = query->clave.i_clave;
103                 hijos_aux[i] = query->num_bloque;
104                 for (j=i+1; j<curnode->cant_claves; j++){
105                         claves_aux[j] = curnode->claves[j-1];
106                         hijos_aux[j] = curnode->hijos[j-1];
107                 }
108                 free(curnode->claves);
109                 free(curnode->hijos);
110                 curnode->claves = claves_aux;
111                 curnode->hijos = hijos_aux;
112                 b_plus_grabar_nodo(idx, curnode, prox_nodo);
113                 b_plus_destruir_nodo(curnode);
114         }
115                 
116         /* si el nodo esta lleno tengo que splitear */
117         if ( curnode->cant_claves == idx->size_claves ) 
118         {
119                 /**FIXME**/
120         }
121         return 0;
122 }
123
124 /** Busca el nro de bloque donde se debe guardar un reg con clave X */
125 /** Si la clave entra en la raiz, la guarda, si no, busca el nodo hoja
126     donde debe ir y devuelve el bloque (en query) pero no graba la clave */
127 /** Devuelve -1 si no hay un bloque donde insertar la nueva clave */
128 int emufs_b_plus_get_bloque(INDEXSPECS *idx, INDEX_DAT *query) {
129
130     NODO_B_PLUS *curnode;
131         int i, prox_nodo;
132         /* Comienzo leyendo la raiz, entry point de toda funcion */
133         printf ("Buscando donde insertar clave: %i\n\n",query->clave.i_clave);
134         curnode = b_plus_leer_nodo(idx,0);      
135         if (curnode == NULL) return -1;
136         /* Me fijo si la raiz esta vacia */
137         if ( curnode->cant_claves == 0 ){ /* entra la clave en la raiz */ 
138                 /* ojo que este es un caso muy particular */
139                 /* aumento la cant de claves*/
140                 curnode->cant_claves++;
141                 /* inserto la clave en el nodo, como es la primera no hace falta ordenar nada*/
142                 *(curnode->claves) = query->clave.i_clave;
143                 /* En query->num_bloque viene un numero de bloque nuevo valido..*/
144                 /* Le asigno al nodo del arbol el mismo numero que venia en query*/
145                 *(curnode->hijos) = query->num_bloque;
146                 /* Cargado el query salgo de la func, luego habra que actualizar el .dat */
147                 /*grabo el nodo en el archivo*/
148                 b_plus_grabar_nodo(idx, curnode, 0);
149                 /* librero el nodo */
150                 b_plus_destruir_nodo(curnode);
151                 return 0;
152         } 
153         PERR("TENGO LA HOJA");  
154         /* Mientras no encontre la hoja con la clave, busco.. */
155         /* RECORDAR QUE LAS CLAVES DEBEN ESTAR ORDENADAS PARA QUE ESTO FUNCIONE !! */ 
156         while (curnode->nivel > 0 && curnode){  
157                 /*recorro las claves hasta encontrar la primera mayor a la que quiero insertar*/
158                 for(i=0; i<curnode->cant_claves; i++){ 
159                         /* me fijo que si es mayor */
160                         if ( (query->clave.i_clave > curnode->claves[i])) {
161                                 if ( curnode->cant_claves != i ) /* si no es la ultima clave del nodo */
162                                         continue; /*paso a la siguiente*/
163                                 else {  /* si era la ultima, la clave deberia ir ahi */
164                                         /*cargo el proximo nodo*/
165                                         prox_nodo = curnode->hijos[i+1];
166                                         break; /*salgo del for*/
167                                 }
168                         } else {  /*si no es mayor o igual es menor*/
169                                 prox_nodo = curnode->hijos[i];
170                                 break;
171                         }
172                 }
173                 b_plus_destruir_nodo(curnode);
174                 curnode = b_plus_leer_nodo(idx, prox_nodo);
175         } 
176         
177         /*cuando salgo de aca deberia tener cargado en curnode el nodo hoja que busque*/
178         for (i=0; i<curnode->cant_claves-1; i++){
179                 if ( query->clave.i_clave >= curnode->claves[i] ){
180                         if ( curnode->cant_claves != i ) /* si no es la ultima clave */
181                                 continue;
182                         else {   /* si era la ultima */
183                                 /* Cargo en query el numero del bloque donde deberia ir la nueva clave */
184                                 query->num_bloque = curnode->hijos[i];
185                                 b_plus_destruir_nodo(curnode);
186                                 return 0;
187                         }
188                 } else {  /* si no era mayor, era menor */
189                         if ( i == 0 ){ 
190                                                                 
191                                 /* ACA PODRIAMOS RETORNAR -1 COMO CODIGO DE ERROR QUE INFORMARIA QUE NO EXISTE 
192                                    UN NODO DONDE QUEPA LA CLAVE, ENTONCES HABRIA QUE LLAMAR A LA FUNCION QUE
193                                    ACTUALIZA EL ARBOL Y SE ENCARGA DE ARGREGAR LA CLAVE Y HACER EL SPLIT DE SER 
194                                    NECESARIO */
195                                 /* Llamo a la funcion que mete una clave nueva en el arbol y le paso el bloque a donde 
196                                    tiene que apuntar */
197                                 b_plus_insertar_clave(idx, query);
198                                 b_plus_destruir_nodo(curnode);
199                                 return 1; /* SE INSERTO NODO NUEVO */
200                         } else {
201                                 query->num_bloque = curnode->hijos[i-1];
202                                 b_plus_destruir_nodo(curnode);
203                                 return 0;
204                         }
205                 }
206         }
207
208         if (curnode) b_plus_destruir_nodo(curnode);
209         return 0;
210 }
211
212 NODO_B_PLUS *b_plus_leer_nodo(INDEXSPECS *idx, int num_node) {
213
214         int i = 0;
215         FILE *fp;
216         NODO_B_PLUS *memnode = b_plus_crearnodo(idx);   
217         char *disknode = (char*)malloc(idx->tam_bloque);
218         
219         if (disknode == NULL) return NULL;
220         if (memnode == NULL) return NULL;
221         
222     /* Open up file */
223         fp = fopen(idx->filename, "r+");
224         if (fp == NULL) {
225                 free(disknode);
226                 b_plus_destruir_nodo(memnode);
227                 return NULL;
228         }
229
230         /* Intentamos leer un nodo, sino podemos error! */
231         fseek(fp, num_node*idx->tam_bloque, SEEK_SET);
232         if (fread(disknode, idx->tam_bloque, 1, fp) != 1) {
233                 free(disknode);
234                 fclose(fp);
235                 return NULL;
236         }
237         fclose(fp);
238         
239         /* Pudimos leer un nodo de disco, ahora lo transformamos a nodo mem */
240         memcpy(memnode,disknode,SIZE_B_PLUS_HEADER);
241         memcpy(memnode->claves,disknode+SIZE_B_PLUS_HEADER,idx->size_claves);
242         memcpy(memnode->hijos,disknode+SIZE_B_PLUS_HEADER+idx->size_claves,idx->size_hijos);
243         free(disknode);
244         
245         printf("Dumping Node_%i\n",num_node);
246         printf("Nivel: %i  Cant Claves: %i\n",memnode->nivel,memnode->cant_claves);
247         printf("Claves:");
248         for (i = 0; i < idx->size_claves/sizeof(int); ++i) printf(" %i",memnode->claves[i]);
249         printf("\nHijos:");
250         for (i = 0; i < idx->size_hijos/sizeof(int); ++i) printf(" %i",memnode->hijos[i]);
251         printf("\nEnd Dump\n"); 
252         
253         return memnode;
254         
255 }
256
257 int b_plus_grabar_nodo(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_node)
258 {
259         FILE *fp;
260         
261         fp = fopen(idx->filename, "r+");
262         if (fp == NULL) return -1;
263                 
264         fseek(fp,num_node*sizeof(NODO_B_PLUS),SEEK_SET);        
265         fwrite(nodo,SIZE_B_PLUS_HEADER,1,fp);
266         fwrite(nodo->claves,idx->size_claves,1,fp);
267         fwrite(nodo->hijos,idx->size_hijos,1,fp);
268         fclose(fp);
269         
270         return 0;
271 }
272
273 int b_plus_destruir_nodo(NODO_B_PLUS *nodo)
274 {
275         free(nodo->claves);
276         free(nodo->hijos);
277         free(nodo);
278         return 0;
279 }
280
281 int b_plus_insert_nonfull(INDEXSPECS *idx, NODO_B_PLUS *nodo, int num_nodo, int num_nodo_padre, CLAVE clave)
282 {
283     int i, num_nodo_hijo;
284     NODO_B_PLUS *hijo;
285     
286     i = nodo->cant_claves;
287     if ( nodo->nivel == 0 ){
288         while ( i >= 1 && clave.i_clave < nodo->claves[i] ){
289             nodo->claves[i+1] = nodo->claves[i];
290             i--;
291         }
292         nodo->claves[i+1] = clave.i_clave;
293         nodo->cant_claves++;
294         b_plus_destruir_nodo(nodo);
295         b_plus_grabar_nodo(idx, nodo, num_nodo);
296     } else { 
297         while ( i >= 1 && clave.i_clave < nodo->claves[i] ) 
298             i--;
299         i++;
300         num_nodo_hijo = nodo->hijos[i-1];
301         hijo = b_plus_leer_nodo(idx, num_nodo_hijo);
302         if ( hijo->cant_claves == idx->size_claves/sizeof(int) ) {
303             b_plus_split_child(idx, nodo, i, hijo);
304             if ( clave.i_clave > nodo->claves[i] )
305                 i++;
306         }
307         b_plus_insert_nonfull(idx, hijo, num_nodo_hijo, num_nodo_padre);
308     }
309     b_plus_destruir_nodo(hijo);
310     return 0;
311 }    
312
313 int b_tree_insertar(INDEXSPECS *idx, CLAVE clave)
314 {
315     NODO_B_PLUS *raiz;
316     
317     raiz = b_plus_leer_nodo(idx, 0);
318     if ( raiz->cant_claves == idx->size_claves/sizeof(int) ) {
319         NODO_B_PLUS *new_root = b_plus_crearnodo(idx);
320         new_root->nivel = raiz->nivel + 1;
321         new_root->hijos[0] = b_plus_get_num_nodo(idx);
322         b_plus_grabar_nodo(idx, raiz, new_root->hijos[0]);
323         b_plus_grabar_nodo(idx, new_root, 0);
324         b_plus_split_child(idx, new_root, 1, raiz);
325         b_plus_insert_nonfull(idx, new_root, 0, clave);
326     } else b_plus_insert_nonfull(idx, raiz, 0, clave);
327     
328     return 0;
329 }
330
331 int b_plus_get_num_nodo(INDEXSPECS *idx)
332 {
333         FILE *fp;
334         int num;
335         
336         fp = fopen(idx->filename, "r+");
337         if (fp == NULL) return -1;
338     
339     num = ftell(fp)/sizeof(NODO_B_PLUS);
340     fclose(fp);
341     return num;
342 }