]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/indice_b_asc.c
Piloteado de mini bug que pudiera existir en insertar ordenado, siempre se devuelve...
[z.facultad/75.06/emufs.git] / emufs / indice_b_asc.c
1
2
3 static void b_asc_insertar_en_nodo(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo1, int hijo2);
4
5 int emufs_indice_b_asc_insertar(INDICE *idx, CLAVE clave, INDICE_DATO dato)
6 {
7         int i, nodo_id, padre_id;
8         B_NodoHeader header;
9         B_NodoEntry *claves;
10         char *nodo, *padre;
11         INDICE_DATO dummy;
12         
13         /* Leo la raiz */
14         nodo = b_leer_nodo(idx, 0);
15         padre_id = nodo_id = 0;
16         padre = NULL;
17         while (nodo) {
18                 if (padre) free(padre);
19                 padre = nodo;
20                 padre_id = nodo_id;
21                 b_leer_header(nodo, &header);
22                 claves = b_leer_claves(nodo, &header);
23                 i=0;
24                 while ((i<header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) i++;
25                 if ((i<header.cant) && (emufs_indice_es_igual(idx, claves[i].clave, clave))) {
26                         if (idx->funcion == IND_PRIMARIO) {
27                                 PERR("Indice primario no puede contener claves duplicadas!");
28                                 PERR(idx->nombre);
29                                 return 0;
30                         }
31                         
32                         b_insertar_dup_en_pos(idx, claves[i].dato, dato);
33                 
34                         if (idx->tipo_dato == IDX_STRING) {
35                                 /* Tengo que sacar el texto repetido del archivo de textos */
36                                 idx->emu_string->borrar_registro(idx->emu_string, clave, dummy);
37                         }
38                         return 1;
39                 } else {
40                         if (i == 0) {
41                                 nodo = b_leer_nodo(idx, header.hijo_izquierdo);
42                                 nodo_id = header.hijo_izquierdo;
43                         } else {
44                                 nodo = b_leer_nodo(idx, claves[i-1].hijo_derecho);
45                                 nodo_id = claves[i-1].hijo_derecho;
46                         }
47                 }
48         }
49
50         if (nodo) free(nodo);
51         nodo = padre;
52         nodo_id = padre_id;
53
54         if (idx->funcion != IND_PRIMARIO) {
55                 /* Agrego el DATO real al archivo de claves repetiras
56                  * y me guardo el ID para poner en el indice
57                  */
58                 dummy.id = -1;
59                 dato.id = b_insertar_dup_en_pos(idx, dummy, dato);
60         }
61
62         b_asc_insertar_en_nodo(idx, clave, dato, nodo_id, nodo, -1, -1);
63         return 1; /* Agregar OK! */
64 }
65
66
67 static void b_asc_insertar_en_nodo(INDICE *idx, CLAVE clave, INDICE_DATO dato, int nodo_id, char *nodo, int hijo1, int hijo2)
68 {
69         char *padre, *nuevo;
70         int nuevo_id;
71         int i, j;
72         static int rompi=0;
73         char salir = 0;
74         char *izq, *der;
75         B_NodoHeader nodo_header, nuevo_header;
76         B_NodoEntry *claves, *tmp_claves, *claves_nuevo;
77
78         do {
79                 if (!nodo) {
80                         /* CREAR NODO? */
81                         nodo = b_crear_nodo(idx, &nodo_id);
82                 }
83                 b_leer_header(nodo, &nodo_header);
84                 claves = b_leer_claves(nodo, &nodo_header);
85
86                 padre = b_leer_nodo(idx, nodo_header.padre);
87
88                 if (nodo_header.cant == CANT_HIJOS(idx)) {
89                         int total;
90                         if (nodo_id != 0) {
91                                 int izq_id, der_id, pos_padre, i;
92                                 B_NodoHeader padre_header, header_der, header_izq;
93                                 B_NodoEntry *padre_claves, nuevo_entry;
94                                 B_NodoEntry a_pasar, *buffer, clave_que_sale;
95
96                                 b_leer_header(padre, &padre_header);
97                                 padre_claves = b_leer_claves(padre, &padre_header);
98
99                          /* nuevo_entry = new entry(clave, dato, hijo_der) */
100                                 PERR("Buscando que hijo soy");
101                                 for(pos_padre=0; (padre_claves[pos_padre].hijo_derecho != nodo_id); pos_padre++)        {       }
102
103                                 if (pos_padre == padre_header.cant) {
104                                         PERR("ERROR GRAVE. Padre no me contiene :-(");
105                                 }
106
107                                 /* Busco mis hermanos a derecha e izquierda, si es que existen */
108                                 PERR("Ya me encontre, busco a mis hermanos");
109                                 if (pos_padre >= 0) {
110                                         if (pos_padre == 0)
111                                                 izq_id = padre_header.hijo_izquierdo;
112                                         else
113                                                 izq_id = padre_claves[pos_padre-1].hijo_derecho;
114                                         izq = b_leer_nodo(idx, izq_id);
115                                         b_leer_header(izq, &header_izq);
116                                 } else {
117                                         izq_id = -1;
118                                 }
119                                 if (pos_padre < padre_header.cant) {
120                                         der_id = padre_claves[pos_padre+1].hijo_derecho;
121                                         der = b_leer_nodo(idx, der_id);
122                                         b_leer_header(der, &header_der);
123                                 } else {
124                                         der_id = -1;
125                                 }
126                                 PERR("Hermanos encontrados");
127
128                                 buffer = malloc((nodo_header.cant+1)*sizeof(B_NodoEntry));
129
130                                 nuevo_entry.clave = clave;
131                                 nuevo_entry.dato = dato;
132                                 nuevo_entry.hijo_derecho = hijo2;
133                                 
134                                 /* Inserto ordenado */
135                                 for(i=0; (i<nodo_header.cant) && emufs_indice_es_menor(idx, claves[i].clave, clave); i++)
136                                         buffer[i] = claves[i];
137                                 buffer[i] = nuevo_entry;
138                                 while (i<nodo_header.cant) {
139                                         buffer[i+1] = claves[i];
140                                         i++;
141                                 }
142
143                                 if ((der_id != -1) && (header_der.cant < CANT_HIJOS(idx))) {
144                                         /* tomo la clave mas grande */
145                                         a_pasar = buffer[nodo_header.cant];
146
147                                         /* la paso a la derecha */
148                                         b_pasar_clave_a_derecha(idx, der, der_id, padre, nodo_header.padre, pos_padre, a_pasar);
149                                         /* Dejo en nodo las claves que corresponden */
150                                         memcpy(claves, buffer, nodo_header.cant*sizeof(B_NodoEntry));
151                                         b_grabar_nodo(idx, der_id, der);
152                                         b_grabar_nodo(idx, nodo_header.padre, padre);
153                                         b_grabar_nodo(idx, nodo_id, nodo);
154                                         free(buffer);
155                                         free(nodo);
156                                         free(der);
157                                         free(padre);
158                                         return;
159                                 } 
160                         
161                                 if ((izq_id != -1) && (header_izq.cant < CANT_HIJOS(idx))) {
162                                         PERR("ESTOY PASANDO CLAVE A IZQUIERDA");
163                                         a_pasar = buffer[0];
164                                         fprintf(stderr, "YO=%d , a_pasar=%d\n", clave.i_clave, a_pasar.clave.i_clave);
165                                         b_pasar_clave_a_izquierda(idx, izq, izq_id, padre, nodo_header.padre, pos_padre, a_pasar, hijo1, padre_claves[pos_padre].hijo_derecho);
166                                         /* Pongo las claves que quedan en el nodo */
167                                         memcpy(claves, buffer+1, nodo_header.cant*sizeof(B_NodoEntry));
168                                         b_grabar_nodo(idx, izq_id, izq);
169                                         b_grabar_nodo(idx, nodo_header.padre, padre);
170                                         b_grabar_nodo(idx, nodo_id, nodo);
171                                         free(buffer);
172                                         free(nodo);
173                                         free(izq);
174                                         free(padre);
175                                         return;
176                                 }
177                         
178                                 /* Tengo que partir, tengo que sacar una clave del padre y mandarla al partir */
179                                 clave_que_sale = padre_claves[pos_padre];
180                                 clave_que_sale.hijo_derecho = -1;
181                                 for(i=pos_padre; i<padre_header.cant-1; i++)
182                                         padre_claves[i] = padre_claves[i+1];
183                                 padre_header.cant--;
184                                 b_actualizar_header(padre, &padre_header);
185                                 b_grabar_nodo(idx, nodo_header.padre, padre);
186                                 if (izq_id != -1)
187                                         b_partir_dos_nodos_en_tres(idx, izq_id, nodo_id, clave_que_sale, nuevo_entry, nodo_header.padre);
188                                 else // Siempre alguno tiene que existir.
189                                         b_partir_dos_nodos_en_tres(idx, nodo_id, der_id, clave_que_sale, nuevo_entry, nodo_header.padre);
190                                 return;
191                         }
192
193                         /* Bueno, soy la raiz, tengo que tratarla como el arbol B */
194                         /* Sigo con a fullllllllll */
195                         nuevo = b_crear_nodo(idx, &nuevo_id);
196                         i=0;
197                         /* Creo una lista ordenada de los nodos a partir */
198                         tmp_claves = (B_NodoEntry *)malloc(sizeof(B_NodoEntry)*(nodo_header.cant+1));
199                         total = nodo_header.cant+1;
200                         while ((i<nodo_header.cant) && (emufs_indice_es_menor(idx, claves[i].clave, clave))) {
201                                 tmp_claves[i] = claves[i];
202                                 i++;
203                         }
204                         tmp_claves[i].clave = clave;
205                         tmp_claves[i].dato = dato;
206                         /*tmp_claves[i].hijo_derecho = hijo1;*/
207                         if (i==0) {
208                                 nodo_header.hijo_izquierdo = hijo1;
209                                 tmp_claves[i].hijo_derecho = hijo2;
210                         } else {
211                                 tmp_claves[i-1].hijo_derecho = hijo1;
212                                 tmp_claves[i].hijo_derecho = hijo2;
213                         }
214                         while (i < nodo_header.cant) {
215                                 tmp_claves[i+1] = claves[i];
216                                 i++;
217                         }
218                         
219                         /* Asigno a cada nodo lo que corresponde */
220                         b_leer_header(nuevo, &nuevo_header);
221
222                         nuevo_header.nivel = nodo_header.nivel;
223                         nodo_header.cant = total/2;
224                         nuevo_header.cant = (total-1) - nodo_header.cant;
225
226                         memset(claves, '*', idx->tam_bloque-sizeof(B_NodoHeader));
227                         for(j=0; j<nodo_header.cant; j++)
228                                 claves[j] = tmp_claves[j];
229
230                         claves_nuevo = b_leer_claves(nuevo, &nuevo_header);
231                         memset(claves_nuevo, '*', idx->tam_bloque-sizeof(B_NodoHeader));
232                         for(j=0; j<nuevo_header.cant; j++)
233                                 claves_nuevo[j] = tmp_claves[j+total/2+1];
234
235                         b_actualizar_header(nodo, &nodo_header);
236                         b_actualizar_header(nuevo, &nuevo_header);
237
238                         if (nodo_id != 0) {
239                                 clave = tmp_claves[total/2].clave;
240                                 dato = tmp_claves[total/2].dato;
241
242                                 b_grabar_nodo(idx, nodo_id, nodo);
243                                 b_grabar_nodo(idx, nuevo_id, nuevo);
244                                 free(nodo);
245                                 free(nuevo);
246                                 free(tmp_claves);
247
248                                 hijo1 = nodo_id;
249                                 hijo2 = nuevo_id;
250
251                                 fprintf(stderr, "Nodos espliteados = %d %d\n", hijo1, hijo2);
252                                 nodo = padre;
253                                 nodo_id = nodo_header.padre;
254                         } else {
255                                 /* Oops, parti el raiz, y este debe quedar en 0, lo paso a otro bloque
256                                  * y dejo el padre vacio
257                                  */
258                                 char *tmp_nuevo = b_crear_nodo(idx, &nodo_id);
259                                 memcpy(tmp_nuevo, nodo, idx->tam_bloque);
260                                 free(nodo);
261                                 nodo = tmp_nuevo;
262         
263                                 clave = tmp_claves[total/2].clave;
264                                 dato = tmp_claves[total/2].dato;
265
266                                 b_grabar_nodo(idx, nuevo_id+1, nodo);
267                                 b_grabar_nodo(idx, nuevo_id, nuevo);
268                 
269                                 free(nodo);
270                                 free(nuevo);
271                                 free(tmp_claves);
272
273                                 hijo1 = nuevo_id+1;
274                                 hijo2 = nuevo_id;
275
276                                 fprintf(stderr, "Nodos espliteados = %d %d\n", hijo1, hijo2);
277                                 /* Limpio al padre */
278                                 nuevo = b_leer_nodo(idx, 0);
279
280                                 b_leer_header(nuevo, &nuevo_header);
281                                 nuevo_header.cant = 0;
282                                 nuevo_header.padre = -1;
283                                 nuevo_header.nivel = nodo_header.nivel+1;
284                                 nuevo_header.hijo_izquierdo = -1;
285                                 fprintf(stderr, "root.nivel=%d\n", nuevo_header.nivel);
286                                 memset(nuevo, -1, idx->tam_bloque);
287                                 b_actualizar_header(nuevo, &nuevo_header);
288                                 b_grabar_nodo(idx, 0, nuevo);
289
290                                 nodo_id = 0;
291                                 nodo = nuevo;
292                                 rompi = 1;
293                         }
294                 } else {
295                         /* La clave entra en este nodo!! */
296                         b_insertar_en_nodo_con_lugar(idx, clave, dato, nodo_id, nodo, hijo1, hijo2);
297                         salir = 1;
298                 }
299         } while (!salir);
300 }
301