]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/indices.c
Ultimas correcciones.
[z.facultad/75.06/emufs.git] / emufs / indices.c
1
2 #include "indices.h"
3 #include "emufs.h"
4 #include "indice_b.h"
5 #include "indice_bplus.h"
6
7 INDICE *emufs_indice_crear(EMUFS *emu, char *nombre, INDICE_FUNCION funcion, INDICE_TIPO tipo, INDICE_TIPO_DATO tipo_dato, unsigned int offset, unsigned int tam_bloque, int str_offset)
8 {
9         int len,cantclaves;
10         INDICE *tmp;
11         
12         char string_file[255];
13         tmp = (INDICE *)malloc(sizeof(INDICE));
14         if (tmp == NULL) return NULL;
15
16         len = strlen(emu->nombre);
17         len += strlen(nombre);
18
19         tmp->filename = (char *)malloc(sizeof(char)*(len+6));
20         strcpy(tmp->filename, emu->nombre);
21         strcat(tmp->filename, "_");
22         strcat(tmp->filename, nombre);
23         strcat(tmp->filename, ".idx");
24
25         tmp->padre = emu;
26         tmp->nombre = (char *)malloc(sizeof(char)*(strlen(nombre)+1));
27         strcpy(tmp->nombre, nombre);
28
29         tmp->tipo = tipo;
30         tmp->tipo_dato = tipo_dato;
31         switch (tipo_dato) {
32                 case IDX_STRING:
33                         sprintf(string_file, "%s_%s_%s", emu->nombre, nombre, "string");
34                         tmp->emu_string = emufs_crear(string_file, T2, 0, 0);
35                 break;
36                 case IDX_FLOAT:
37                 case IDX_INT:
38                         tmp->emu_string = NULL;
39         }
40
41         tmp->tam_bloque = tam_bloque;
42         tmp->funcion = funcion;
43         switch (funcion) {
44                 case IND_PRIMARIO:
45                         tmp->emu_mult = NULL;
46                 break;
47                 case IND_SELECCION:
48                 case IND_EXAHUSTIVO:
49                         sprintf(string_file, "%s_%s_%s", emu->nombre, nombre, "multiples");
50                         tmp->emu_mult = emufs_crear(string_file, T2, 0, 0);
51         }
52
53         tmp->offset = offset;
54         tmp->str_offset = str_offset;
55         tmp->sig = NULL;
56         tmp->size_claves = 0;
57         tmp->size_hijos = 0;
58         tmp->keybucket = NULL;
59
60         switch (tmp->tipo) {
61                 case IND_B:
62                         PERR("Creando indice con Arbol B");
63                         emufs_indice_b_crear(tmp);
64                         tmp->agregar_entrada = emufs_indice_b_insertar;
65                         tmp->borrar_entrada = emufs_indice_b_borrar;
66                         tmp->existe_entrada = emufs_indice_b_buscar;
67                         tmp->buscar_entradas = emufs_indice_b_buscar_muchos;
68                         tmp->obtener_menor_clave = emufs_indice_b_obtener_menor_clave;
69                         tmp->obtener_mayor_clave = emufs_indice_b_obtener_mayor_clave;
70                         tmp->obtener_sig_clave = emufs_indice_b_obtener_sig_clave;
71                 break;
72                 case IND_B_ASC:
73                         /* llenar metodos */
74                         PERR("Creando indice con Arbol B*");
75                         emufs_indice_b_crear(tmp);
76                         tmp->agregar_entrada = emufs_indice_b_asc_insertar;
77                         tmp->borrar_entrada = emufs_indice_b_borrar;
78                         tmp->existe_entrada = emufs_indice_b_buscar;
79                         tmp->buscar_entradas = emufs_indice_b_buscar_muchos;
80                         tmp->obtener_menor_clave = emufs_indice_b_obtener_menor_clave;
81                         tmp->obtener_mayor_clave = emufs_indice_b_obtener_mayor_clave;
82                         tmp->obtener_sig_clave = emufs_indice_b_obtener_sig_clave;
83                         break;
84                 case IND_B_PLUS:
85                         /* llenar metodos */
86                         /* hacer que la cantidad de claves quede par o impar, no me acuerdo (SAGAR)!!!*/
87                         PERR("Creando indice con Arbol B+");
88                         tmp->size_claves = (tmp->tam_bloque - SIZE_B_PLUS_HEADER - sizeof(CLAVE))/2;
89                         cantclaves = tmp->size_claves/sizeof(CLAVE);                    
90                         if ((cantclaves%2) == 0 ) {
91                                 tmp->size_claves = (cantclaves+1)*sizeof(CLAVE);                                
92                                 tmp->size_hijos = tmp->size_claves + sizeof(CLAVE);
93                                 tmp->tam_bloque = SIZE_B_PLUS_HEADER + tmp->size_hijos + tmp->size_claves;
94                                 PERR("Ajusto cantidad de claves impares en B+");
95                         } else  {
96                                 tmp->size_claves = cantclaves*sizeof(CLAVE);                            
97                                 tmp->size_hijos = tmp->size_claves + sizeof(CLAVE);
98                                 tmp->tam_bloque = SIZE_B_PLUS_HEADER + tmp->size_hijos + tmp->size_claves;
99                                 PERR("No Ajusto cantidad de claves impares en B+");
100                         }
101                         emufs_b_plus_crear(tmp);
102                         tmp->obtener_menor_clave = emufs_b_plus_obtener_menor_clave;
103                         tmp->obtener_mayor_clave = emufs_b_plus_obtener_mayor_clave;
104                         tmp->obtener_sig_clave = emufs_b_plus_obtener_sig_clave;
105                         break;
106         }
107
108         return tmp;
109 }
110
111 INDICE *emufs_indice_abrir(EMUFS *emu, char *nombre, INDICE_FUNCION funcion, INDICE_TIPO tipo, INDICE_TIPO_DATO tipo_dato, unsigned int offset, unsigned int tam_bloque, int str_offset)
112 {
113         int len,cantclaves;
114         INDICE *tmp;
115         char string_file[255];
116         tmp = (INDICE *)malloc(sizeof(INDICE));
117         if (tmp == NULL) return NULL;
118
119         len = strlen(emu->nombre);
120         len += strlen(nombre);
121
122         tmp->filename = (char *)malloc(sizeof(char)*(len+6));
123         strcpy(tmp->filename, emu->nombre);
124         strcat(tmp->filename, "_");
125         strcat(tmp->filename, nombre);
126         strcat(tmp->filename, ".idx");
127
128         tmp->nombre = (char *)malloc(sizeof(char)*(strlen(nombre)+1));
129         strcpy(tmp->nombre, nombre);
130         tmp->padre = emu;
131         tmp->tipo = tipo;
132         tmp->tipo_dato = tipo_dato;
133         switch (tipo_dato) {
134                 case IDX_STRING:
135                         sprintf(string_file, "%s_%s_%s", emu->nombre, nombre, "string");
136                         tmp->emu_string = emufs_abrir(string_file);
137                 break;
138                 case IDX_FLOAT:
139                 case IDX_INT:
140                         tmp->emu_string = NULL;
141         }
142
143         tmp->tam_bloque = tam_bloque;
144         tmp->funcion = funcion;
145         switch (funcion) {
146                 case IND_PRIMARIO:
147                         tmp->emu_mult = NULL;
148                 break;
149                 case IND_SELECCION:
150                 case IND_EXAHUSTIVO:
151                         sprintf(string_file, "%s_%s_%s", emu->nombre, nombre, "multiples");
152                         tmp->emu_mult = emufs_abrir(string_file);
153         }
154
155         tmp->offset = offset;
156         tmp->str_offset = str_offset;
157         tmp->sig = NULL;
158         tmp->size_claves = 0;
159         tmp->size_hijos = 0;
160         tmp->keybucket = NULL;
161
162         switch (tmp->tipo) {
163                 case IND_B:
164                         PERR("Creando indice con Arbol B");
165                         /* Ya esta creado XXX emufs_indice_b_crear(tmp); */
166                         tmp->agregar_entrada = emufs_indice_b_insertar;
167                         tmp->borrar_entrada = emufs_indice_b_borrar;
168                         tmp->existe_entrada = emufs_indice_b_buscar;
169                         tmp->buscar_entradas = emufs_indice_b_buscar_muchos;
170                         tmp->obtener_menor_clave = emufs_indice_b_obtener_menor_clave;
171                         tmp->obtener_mayor_clave = emufs_indice_b_obtener_mayor_clave;
172                         tmp->obtener_sig_clave = emufs_indice_b_obtener_sig_clave;
173                 break;
174                 case IND_B_ASC:
175                         /* llenar metodos */
176                         PERR("Creando indice con Arbol B*");
177                         /* Ya esta creado XXX emufs_indice_b_crear(tmp); */
178                         tmp->agregar_entrada = emufs_indice_b_asc_insertar;
179                         tmp->borrar_entrada = emufs_indice_b_borrar;
180                         tmp->existe_entrada = emufs_indice_b_buscar;
181                         tmp->buscar_entradas = emufs_indice_b_buscar_muchos;
182                         tmp->obtener_menor_clave = emufs_indice_b_obtener_menor_clave;
183                         tmp->obtener_mayor_clave = emufs_indice_b_obtener_mayor_clave;
184                         tmp->obtener_sig_clave = emufs_indice_b_obtener_sig_clave;
185                         break;
186                 case IND_B_PLUS:
187                         /* llenar metodos */
188                         /* hacer que la cantidad de claves quede par o impar, no me acuerdo (SAGAR)!!!*/
189                         PERR("Creando indice con Arbol B+");
190                         tmp->size_claves = (tmp->tam_bloque - SIZE_B_PLUS_HEADER - sizeof(CLAVE))/2;
191                         cantclaves = tmp->size_claves/sizeof(CLAVE);                    
192                         if ((cantclaves%2) == 0 ) {
193                                 tmp->size_claves = (cantclaves+1)*sizeof(CLAVE);                                
194                                 tmp->size_hijos = tmp->size_claves + sizeof(CLAVE);
195                                 tmp->tam_bloque = SIZE_B_PLUS_HEADER + tmp->size_hijos + tmp->size_claves;
196                                 PERR("Ajusto cantidad de claves impares en B+");
197                         } else  {
198                                 tmp->size_claves = cantclaves*sizeof(CLAVE);                            
199                                 tmp->size_hijos = tmp->size_claves + sizeof(CLAVE);
200                                 tmp->tam_bloque = SIZE_B_PLUS_HEADER + tmp->size_hijos + tmp->size_claves;
201                                 PERR("No Ajusto cantidad de claves impares en B+");
202                         }
203                         /* Ya esta creado XXX emufs_b_plus_crear(tmp); */
204                         tmp->obtener_menor_clave = emufs_b_plus_obtener_menor_clave;
205                         tmp->obtener_mayor_clave = emufs_b_plus_obtener_mayor_clave;
206                         PERR("AÚN NO IMPLEMENTADO DEL TODO!!!!!!!!");
207                         break;
208         }
209
210         return tmp;
211 }
212
213 void emufs_indice_destruir(EMUFS *emu, INDICE *i)
214 {
215         /* TODO Sacar el indice de la lista en EMUFS */
216
217         if (!i) return;
218
219         if (i->tipo == IDX_STRING)
220                 emufs_destruir(i->emu_string);
221         if (i->funcion != IND_PRIMARIO)
222                 emufs_destruir(i->emu_mult);
223         free(i->filename);
224         free(i->nombre);
225         free(i);
226 }
227
228 void emufs_indice_agregar(INDICE *primero, char *data, INDICE_DATO dato)
229 {
230         INDICE *iter = primero;
231
232         while (iter) {
233                 iter->agregar_entrada(iter, emufs_indice_generar_clave(iter, data), dato);
234                 iter = iter->sig;
235         }
236 }
237
238 INDICE_DATO emufs_indice_buscar(INDICE *primero, char *data)
239 {
240         return primero->existe_entrada(primero, emufs_indice_generar_clave_desde_valor(primero, data));
241 }
242
243 CLAVE emufs_indice_generar_clave_desde_valor(INDICE *idx, char *data)
244 {
245         int error;
246         CLAVE k;
247         char salvar[100];
248         if (idx == NULL) PERR("NULL INDEX!");
249
250         switch (idx->tipo_dato) {
251                 case IDX_FLOAT:
252                         k.f_clave= *((float *)(data));
253                 break;
254                 case IDX_INT:
255                         k.i_clave = *((int *)(data));
256                 break;
257                 case IDX_STRING:
258                         /* TODO : Esto deja basura en el archivo.
259                          * Ver de borrarla despues de usarla
260                          */
261                         error = 0;
262                         /* Le agrego un * para diferenciarla, porque no la tengo abreviada! */
263                         /* Hack feo :-D */
264                         sprintf(salvar, "%s", data);
265                         k.i_clave = idx->emu_string->grabar_registro(idx->emu_string,
266                                 salvar,
267                                 strlen(salvar)+1,
268                                 &error
269                         );
270         }
271
272         return k;
273 }
274
275 CLAVE emufs_indice_generar_clave(INDICE *idx, char *data)
276 {
277         CLAVE k;
278         int error;
279         int c;
280         char *ptr;
281
282         switch (idx->tipo_dato) {
283                 case IDX_FLOAT:
284                         k.f_clave= *((float *)(data+idx->offset));
285                 break;
286                 case IDX_INT:
287                         k.i_clave = *((int *)(data+idx->offset));
288                 break;
289                 case IDX_STRING:
290                         /* Tengo que buscar donde empieza el campo */
291                         ptr = data + idx->offset;
292                         c = idx->str_offset;
293
294                         while (c) {
295                                 if ((*ptr) == '\0') {
296                                         c--;
297                                         /* Salteo los \0 seguidos */
298                                         if (idx->padre->tipo == T3)
299                                                 while ((*ptr) == '\0') ptr++;
300                                         else
301                                                 ptr++;
302                                 } else
303                                         ptr++;
304                         }
305                         error = 0;
306                         k.i_clave = idx->emu_string->grabar_registro(idx->emu_string,
307                                 ptr,
308                                 strlen(ptr)+1,
309                                 &error
310                         );
311         }
312
313         return k;
314 }
315
316 int emufs_indice_es_menor(INDICE *idx, CLAVE c1, CLAVE c2)
317 {
318         char *sc1, *sc2; /* Si es IDX_STRING aca pongo los strings leidos */
319         EMUFS_REG_SIZE dummy; /* No me interesa el tamaño del string aca! */
320         int error=0, a, b;
321
322         switch (idx->tipo_dato) {
323                 case IDX_FLOAT:
324                         return c1.f_clave < c2.f_clave;
325                 case IDX_INT:
326                         return c1.i_clave < c2.i_clave;
327                 case IDX_STRING:
328                         error = 0;
329                         sc1 = idx->emu_string->leer_registro(idx->emu_string, c1, &dummy, &error);
330                         error = 0;
331                         sc2 = idx->emu_string->leer_registro(idx->emu_string, c2, &dummy, &error);
332                         /* Salteo el caracter que indica si la clave en temporal */
333                         a = b = 0;
334                         if (*sc1 == '*') a = 1;
335                         if (*sc2 == '*') b = 1;
336                         error = (strcmp(sc1, sc2) < 0);
337                         free(sc1);
338                         free(sc2);
339                         return error;
340         }
341         return 0;
342 }
343
344 int emufs_indice_es_igual(INDICE *idx, CLAVE c1, CLAVE c2)
345 {
346         char *sc1, *sc2; /* Si es IDX_STRING aca pongo los strings leidos */
347         EMUFS_REG_SIZE dummy; /* No me interesa el tamaño del string aca! */
348         int error, a, b;
349
350         switch (idx->tipo_dato) {
351                 case IDX_FLOAT:
352                         return c1.f_clave == c2.f_clave;
353                 case IDX_INT:
354                         return c1.i_clave == c2.i_clave;
355                 case IDX_STRING:
356                         error = 0;
357                         sc1 = idx->emu_string->leer_registro(idx->emu_string, c1, &dummy, &error);
358                         if (sc1 == NULL) return 0;
359                         error = 0;
360                         sc2 = idx->emu_string->leer_registro(idx->emu_string, c2, &dummy, &error);
361                         if (sc2 == NULL) {
362                                 free(sc2);
363                                 return 0;
364                         }
365                         /* Salteo el caracter que indica si la clave en temporal */
366                         a = b = 0;
367                         if (*sc1 == '*') a=1;
368                         if (*sc2 == '*') b=1;
369                         error = (strcmp(sc1, sc2) == 0);
370                         free(sc1);
371                         free(sc2);
372                         return error;
373         }
374         return 0;
375 }
376
377 void emufs_indice_obtener_valor_desde_clave(INDICE *idx, CLAVE k, void *dst)
378 {
379         int error;
380         char *leido;
381         EMUFS_REG_SIZE dummy;
382
383         switch (idx->tipo_dato) {
384                 case IDX_FLOAT:
385                         (*((float *)dst)) = k.f_clave;
386                 break;
387                 case IDX_INT:
388                         (*((int *)dst)) = k.f_clave;
389                 break;
390                 case IDX_STRING:
391                         error = 0;
392                         leido = idx->emu_string->leer_registro(idx->emu_string, k, &dummy, &error);
393                         strcpy((char *)dst, leido);
394                         free(leido);
395         }
396 }
397
398
399 void emufs_indice_borrar(INDICE *primero, CLAVE k, INDICE_DATO dato)
400 {
401         INDICE *iter = primero;
402
403         while (iter) {
404                 iter->borrar_entrada(iter, k, dato);
405                 iter = iter->sig;
406         }
407 }
408
409 int emufs_indice_es_clave_nula(INDICE *idx, CLAVE k)
410 {
411         char *sc1;
412         EMUFS_REG_SIZE dummy; /* No me interesa el tamaño del string aca! */
413         int error=0;
414
415         switch (idx->tipo_dato) {
416                 case IDX_FLOAT:
417                         return k.f_clave == -1 ;
418                 case IDX_INT:
419                         return k.i_clave == -1;
420                 case IDX_STRING:
421                         error = 0;
422                         sc1 = idx->emu_string->leer_registro(idx->emu_string, k, &dummy, &error);
423                         error = strlen(sc1);
424                         free(sc1);
425                         return error==0;
426         }
427         return 0;
428 }