]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/emufs.c
* BUGFIX : Habia un error al borrar claves que no estaban en las hojas.
[z.facultad/75.06/emufs.git] / emufs / emufs.c
1 /* vim: set noexpandtab tabstop=4 shiftwidth=4:
2  *----------------------------------------------------------------------------
3  *                                  emufs
4  *----------------------------------------------------------------------------
5  * This file is part of emufs.
6  *
7  * emufs is free software; you can redistribute it and/or modify it under the
8  * terms of the GNU General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option) any later
10  * version.
11  *
12  * emufs is distributed in the hope that it will be useful, but WITHOUT ANY
13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15  * details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with emufs; if not, write to the Free Software Foundation, Inc., 59 Temple
19  * Place, Suite 330, Boston, MA  02111-1307  USA
20  *----------------------------------------------------------------------------
21  * Creado:  mié mar 31 17:26:46 ART 2004
22  * Autores: Nicolás Dimov <sagardua@uolsinectis.com.ar>
23  *          Ricardo Markiewicz <rmarkie@fi.uba.ar>
24  *          Leandro Lucarella <llucare@fi.uba.ar>
25  *----------------------------------------------------------------------------
26  *
27  * $Id$
28  *
29  */
30
31 /** \file
32  *
33  * Estructura general de un archivo <em>abstracto</em> de emufs.
34  * 
35  * Implementación de la estructura abstracta que representa cualquiera de los
36  * tipos de archivo implementados. Se incluyen funciones tipo <em>factory</em>
37  * para crear un archivo, abrirlo y destruirlo.
38  *
39  */
40
41 #include "emufs.h"
42 #include "common.h"
43 #include "tipo1.h"
44 #include "tipo2.h"
45 #include "tipo3.h"
46 #include "did.h"
47 #include "fsc.h"
48 #include "idx.h"
49
50 char *str_dup(const char *s);
51
52 char *str_dup(const char *s)
53 {
54         char *tmp;
55         if (s == NULL) return NULL;
56         tmp = (char *)malloc(sizeof(char)*(strlen(s)+1));
57         strcpy(tmp, s);
58         return tmp;
59 }
60
61 int emufs_crear_archivo_auxiliar(const char* name, const char* ext)
62 {
63         FILE* f;
64         char* filename;
65
66         filename = (char*) malloc(sizeof(char) * (strlen(name) + strlen(ext) + 1));
67         if (filename == NULL) {
68                 /* TODO Manejo de errores */
69                 return -1;
70         }
71         strcpy(filename, name);
72         strcat(filename, ext);
73         f = fopen(filename, "w");
74         free(filename);
75         if (f == NULL) {
76                 /* TODO Manejo de errores */
77                 return -1;
78         }
79         fclose(f);
80         return 0;
81 }
82
83 EMUFS *emufs_crear(const char *filename, EMUFS_Tipo tipo, EMUFS_BLOCK_SIZE tam_bloque, EMUFS_REG_SIZE tam_reg)
84 {
85         char name[255];
86         FILE *fp;
87         EMUFS *efs;
88         int err = 0;
89
90         /* Si no es un tipo conocido, sale. */
91         if ((tipo != T1) && (tipo != T2) && (tipo != T3)) {
92                 return NULL;
93         }
94
95         /* Inicializa parámetros comunes. */
96         efs = (EMUFS*) malloc(sizeof(EMUFS));
97         if (efs == NULL) {
98                 return NULL;
99         }
100         efs->tipo = tipo;
101         efs->tam_bloque = tam_bloque;
102         efs->tam_reg = tam_reg;
103         efs->nombre = str_dup(filename);
104         efs->indices = NULL;
105
106         /* Abre archivo de datos. */
107         strcpy(name, filename);
108         strcat(name, ".dat");
109         fp = fopen(name, "w");
110         if (fp == NULL) {
111                 /* TODO ERROR */
112                 free(efs->nombre);
113                 free(efs);
114                 return NULL;
115         }
116
117         /* Guarda cabecera común. */
118         fwrite(&tipo, sizeof(EMUFS_Tipo), 1, fp);
119
120         /* Crea archivo de índice. */
121         if (emufs_idx_crear(efs)) {
122                 /* TODO ERROR */
123                 fclose(fp);
124                 free(efs->nombre);
125                 free(efs);
126                 return NULL;
127         }
128
129         /* Crea archivo de control de espacio libre. */
130         if (emufs_fsc_crear(efs)) {
131                 /* TODO ERROR */
132                 fclose(fp);
133                 free(efs->nombre);
134                 free(efs);
135                 return NULL;
136         }
137
138         /* Crea archivo de identificadores borrados (recuperables). */
139         if (emufs_did_crear(efs)) {
140                 /* TODO ERROR */
141                 fclose(fp);
142                 free(efs->nombre);
143                 free(efs);
144                 return NULL;
145         }
146
147         /* Termina de realizar el trabajo según el tipo de archivo. */
148         switch (tipo) {
149
150                 case T1:
151                         /* Asigna punteros a funciones. */
152                         if ((err = emufs_tipo1_inicializar(efs))) {
153                                 /* TODO ERROR */
154                                 PERR("No se pudo inicializar el EMUFS de tipo1");
155                                 fclose(fp);
156                                 free(efs->nombre);
157                                 free(efs);
158                                 return NULL;
159                         }
160
161                         /* Guarda cabeceras propias. */
162                         fwrite(&tam_bloque, sizeof(EMUFS_BLOCK_SIZE), 1, fp);
163
164                         break;
165
166                 case T2:
167                         /* Asigna punteros a funciones. */
168                         emufs_tipo2_inicializar(efs);
169                         break;
170
171                 case T3:
172                         /* Asigna punteros a funciones. */
173                         efs->leer_bloque = emufs_tipo3_leer_bloque;
174                         efs->leer_registro = emufs_tipo3_leer_registro;
175                         efs->leer_registro_raw = emufs_tipo3_leer_registro_raw;
176                         efs->grabar_registro = emufs_tipo3_grabar_registro;
177                         efs->borrar_registro = emufs_tipo3_borrar_registro;
178                         efs->leer_estadisticas = emufs_tipo3_leer_estadisticas;
179                         efs->modificar_registro = emufs_tipo3_modificar_registro;
180                         efs->compactar = emufs_tipo3_compactar;
181                         efs->leer_bloque_raw = emufs_tipo3_leer_bloque_raw;
182                         /* Guarda cabeceras propias. */
183                         fwrite(&tam_bloque, sizeof(EMUFS_BLOCK_SIZE), 1, fp);
184                         fwrite(&tam_reg, sizeof(EMUFS_REG_SIZE), 1, fp);                        
185                         break;
186
187         }
188
189         fclose(fp);
190         return efs;
191 }
192
193 EMUFS *emufs_abrir(const char *filename)
194 {
195         EMUFS *efs;
196         char name[255];
197         char tipo;
198         FILE *fp;
199         int err = 0;
200
201         strcpy(name, filename);
202         strcat(name, ".dat");
203
204         /* Trato de determinar el tipo de archivo */
205         fp = fopen(name, "r");
206         if (fp == NULL) return NULL;
207         fread(&tipo, sizeof(EMUFS_Tipo), 1, fp);
208
209         /* Si no es un tipo conocido, sale. */
210         if ((tipo != T1) && (tipo != T2) && (tipo != T3)) {
211                 fclose(fp);
212                 return NULL;
213         }
214         
215         /* Inicializa parámetros comunes. */
216         efs = (EMUFS*) malloc(sizeof(EMUFS));
217         if (efs == NULL) {
218                 fclose(fp);
219                 return NULL;
220         }
221         efs->tipo = tipo;
222         efs->nombre = str_dup(filename);
223         
224         switch (tipo) {
225                 case T1:
226                         /* Lee cabeceras propias. */
227                         if (!fread(&(efs->tam_bloque), sizeof(EMUFS_BLOCK_SIZE), 1, fp)) {
228                                 free(efs->nombre);
229                                 free(efs);
230                                 fclose(fp);
231                                 return NULL;
232                         }
233                         /* Asigna punteros a funciones. */
234                         if ((err = emufs_tipo1_inicializar(efs))) {
235                                 PERR("No se pudo inicializar el EMUFS de tipo1");
236                                 fclose(fp);
237                                 return NULL;
238                         }
239                         break;
240                 case T2:
241                         /* Asigna punteros a funciones. */
242                         emufs_tipo2_inicializar(efs);                   
243                         break;
244                 case T3:
245                         if ((!fread(&(efs->tam_bloque), sizeof(EMUFS_BLOCK_SIZE), 1, fp)) ||
246                            (!fread(&(efs->tam_reg), sizeof(EMUFS_REG_SIZE), 1, fp)))
247                                 {
248                                 free(efs->nombre);
249                                 free(efs);
250                                 fclose(fp);
251                                 return NULL;
252                         }                       
253                         /* Asigna punteros a funciones. */                      
254                         efs->leer_bloque = emufs_tipo3_leer_bloque;
255                         efs->leer_registro_raw = emufs_tipo3_leer_registro_raw;
256                         efs->leer_registro = emufs_tipo3_leer_registro;
257                         efs->grabar_registro = emufs_tipo3_grabar_registro;
258                         efs->borrar_registro = emufs_tipo3_borrar_registro;
259                         efs->leer_estadisticas = emufs_tipo3_leer_estadisticas;
260                         efs->modificar_registro = emufs_tipo3_modificar_registro;
261                         efs->compactar = emufs_tipo3_compactar;
262                         efs->leer_bloque_raw = emufs_tipo3_leer_bloque_raw;
263                         break;
264         }
265
266         fclose(fp);
267         return efs;
268 }
269
270 int emufs_destruir(EMUFS *e)
271 {
272         if (e == NULL) return 1;
273         free(e->nombre);
274         free(e);
275         return 0;
276 }
277
278 int ver_archivo_FS(EMUFS *emu)
279 {
280         FILE *f_block_free;
281         EMUFS_FSC reg;
282         char name_f_block_free[255];
283         
284         strcpy(name_f_block_free,emu->nombre);
285         strcat(name_f_block_free,".fsc");
286
287         if ( (f_block_free = fopen(name_f_block_free,"r"))==NULL ){
288                 fprintf(stderr, "no pude abrir el archivo %s\n",name_f_block_free);
289                 return -1;
290         }
291         fprintf(stderr,"BOQUES Y ESPACIO LIBRE\n");
292         fread(&reg,sizeof(reg),1,f_block_free);
293         while ( !feof(f_block_free) ){
294                 fprintf(stderr, "Bloque = %li   Espacio libre = %li\n",reg.marker, reg.freespace);
295                 fread(&reg,sizeof(reg),1,f_block_free);
296         }
297         
298         fclose(f_block_free);
299
300         /* Imprimo la lista de bloques/registros */
301         fprintf(stderr, "BLOQUES Y REGISTROS\n");
302         strcpy(name_f_block_free,emu->nombre);
303         strcat(name_f_block_free,".idx");
304         f_block_free = fopen(name_f_block_free, "r");
305         {
306                 EMUFS_IDX r;
307                 while (!feof(f_block_free)) {
308                         if (fread(&r, sizeof(EMUFS_IDX), 1, f_block_free) != 1) continue;
309                         fprintf(stderr, "ID %li en bloque %li\n", r.id_reg, r.location);
310                 }
311         }
312         fclose(f_block_free);
313         
314         return 0;
315 }
316
317 int debug_ver_estadisticas(EMUFS* efs)
318 {
319         EMUFS_Estadisticas s = efs->leer_estadisticas(efs);
320
321         printf("ESTADISTICAS:\n");
322         printf("=============\n");
323         printf("Tamaño del archivo: %lu bytes\n", s.tam_archivo);
324         printf("Tamaño de datos (incluye espacio libre): %lu bytes (%.2f %%)\n",
325                         s.tam_archivo - s.tam_info_control_dat,
326                         (s.tam_archivo - s.tam_info_control_dat) * 100.0
327                                 / (float) s.tam_archivo);
328         printf("Tamaño de info de control total: %lu bytes (%.2f %%)\n",
329                         s.tam_info_control_dat + s.tam_archivos_aux,
330                         (s.tam_info_control_dat + s.tam_archivos_aux) * 100.0
331                                 / (float) s.tam_archivo);
332         printf("Tamaño de los archivos auxiliares: %lu bytes\n",
333                         s.tam_archivos_aux);
334         printf("Tamaño de la información de control en el .dat: %lu bytes\n",
335                         s.tam_info_control_dat);
336         printf("Total de espacio libre: %lu bytes\n", s.total_fs);
337         printf("Máximo espacio libre en bloque: %lu bytes\n", s.max_fs);
338         printf("Mínimo espacio libre en bloque: %lu bytes\n", s.min_fs);
339         printf("Media del espacio libre por bloque: %lu bytes\n", s.media_fs);
340         printf("Cantidad de registros: %lu\n", s.cant_registros);
341         printf("Cantidad de bloques: %lu\n", s.cant_bloques);
342         return 0;
343 }
344
345 int emufs_agregar_indice(EMUFS *emu, char *nombre, INDICE_FUNCION funcion, INDICE_TIPO tipo, INDICE_TIPO_DATO tipo_dato,  unsigned int offset, unsigned int tam_bloque)
346 {
347         INDICE *tmp;
348         int error=0;
349
350         /* Verifico que no existe un indice con el mismo nombre */
351         /* y que no exista un indice primario */
352         PERR("Agregando indice");
353         tmp = emu->indices;
354         while (tmp) {
355                 if (strcmp(tmp->nombre, nombre)==0) {
356                         error = 1;
357                         break;
358                 }
359                 if ((funcion == IND_PRIMARIO) && (tmp->funcion == funcion)) {
360                         error = 2;
361                         break;
362                 }
363                 tmp = tmp->sig;
364         }
365
366         if (tmp != NULL) {
367                 switch (error) {
368                         case 1:
369                                 PERR("Ya existe un indice con el mismo nombre!");
370                         break;
371                         case 2:
372                                 PERR("EMUFS ya tiene indice primario!!");
373                 }
374                 return 0;
375         }
376
377         /* Creo el nuevo indice */
378         PERR("Creando indice\n");
379         tmp = emufs_indice_crear(emu, nombre, funcion, tipo, tipo_dato, offset, tam_bloque);
380
381         if (tmp == NULL) {
382                 PERR("NO SE PUDO CREAR INDICE!!!");
383                 return 0;
384         }
385
386         if (emu->indices==NULL)
387                 emu->indices = tmp;
388         else {
389                 tmp->sig = emu->indices;
390                 emu->indices = tmp;
391         }
392         return 1;
393 }
394
395 INDICE_DATO *emufs_buscar_registros(EMUFS *emu, char *indice, char *data, int *cant)
396 {
397         CLAVE k;
398         INDICE *tmp;
399
400         tmp = emu->indices;
401         while (tmp) {
402                 if (strcmp(tmp->nombre, indice) == 0) break;
403                 tmp = tmp->sig;
404         }
405
406         if (tmp == NULL) {
407                 PERR("NO EXISTE EL INDICE");
408                 cant = 0;
409                 return NULL;
410         }
411
412         PERR("GENERANDO CLAVE")
413         PERR(data);
414         k = emufs_indice_generar_clave_desde_valor(tmp, data);
415         PERR("DONE");
416         return tmp->buscar_entradas(tmp, k, cant);
417 }
418