]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs/fsc.c
si hubiera una materia que se llame boludos atomicos a mi me la dan por aprobada...
[z.facultad/75.06/emufs.git] / emufs / fsc.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:  vie abr  9 16:17:50 ART 2004
22  * Autores: Nicolás Dimov <sagardua@uolsinectis.com.ar>
23  *          Leandro Lucarella <llucare@fi.uba.ar>
24  *----------------------------------------------------------------------------
25  *
26  * $Id$
27  *
28  */
29
30 /** \file
31  *
32  * Archivo para administrar el espacio libre disponible.
33  * 
34  * Implementación del archivo para administrar el espacio libre disponible.
35  *
36  */
37
38 #include "fsc.h"
39 #include <string.h>
40 #include <unistd.h>
41
42 /* Crea un archivo de Gaps o Espacio Libre en Bloque */
43 int emufs_fsc_crear(EMUFS* efs)
44 {
45         return emufs_crear_archivo_auxiliar(efs->nombre, EMUFS_FSC_EXT);
46 }
47
48 /* Agrega un registro al archivo de espacio libre en bloque. */
49 int emufs_fsc_agregar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
50 {
51         FILE *f_fsc;
52         EMUFS_FSC reg;
53         char name_f_fsc[255];
54         
55         strcpy(name_f_fsc,emu->nombre);
56         strcat(name_f_fsc, EMUFS_FSC_EXT);
57         
58         /* Lo guardo en el archivo al final "a+"*/
59         if ( (f_fsc = fopen(name_f_fsc,"r+"))==NULL ) return -1;
60         /* lo busco.. si esta lo modifico y si no lo agrego */
61         fseek(f_fsc,0,SEEK_SET);
62         while ( !feof(f_fsc) ){
63                 if ( fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
64                 if ( reg.marker == marker ){
65                         fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
66                         reg.freespace = freespace;
67                         fwrite(&reg,sizeof(EMUFS_FSC),1,f_fsc);
68                         fclose(f_fsc);
69                         return 0;
70                 }
71         }
72         /* Cargo el registro */
73         reg.marker = marker;
74         reg.freespace = freespace;
75         fwrite(&reg,sizeof(EMUFS_FSC),1,f_fsc);
76         fclose(f_fsc);
77         return 0;
78 }
79
80 /* Agrega un GAP en el archivo de Gaps para Filetype 2 */
81 int emufs_fsc_agregar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
82 {
83         FILE *f_fsc;
84         EMUFS_FSC gap_aux,gap_before,gap_after,gap_new;
85         char name_f_fsc[255];
86         EMUFS_REG_ID pos_gap_before = 0, pos_gap_after = 0;
87         unsigned long source,destination,file_size,reg_count = 0,cant_moved = 0;
88                 
89         strcpy(name_f_fsc,emu->nombre);
90         strcat(name_f_fsc, EMUFS_FSC_EXT);
91         
92         gap_before.marker = -1;
93         gap_after.marker = -1;
94         
95         /* Busco si hay un GAP por delante y/o por detras del que se esta por crear */
96         /* para en dicho caso realizar un merge! */
97         if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1; 
98         while ( !feof(f_fsc) ){
99                 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
100                 
101                 /* Chequeo si es un gap justo anterior al nuestro */
102                 if (gap_aux.marker+gap_aux.freespace == marker) {
103                         gap_before.marker = gap_aux.marker;
104                         gap_before.freespace = gap_aux.freespace;
105                         pos_gap_before = reg_count;
106                 }
107                 
108                 /* Chequeo si es un gap justo posterior al nuestro */           
109                 if (gap_aux.marker == marker+freespace) {
110                         gap_after.marker = gap_aux.marker;
111                         gap_after.freespace = gap_aux.freespace;
112                         pos_gap_after = reg_count;
113                 }               
114                 reg_count += 1;
115         }
116         
117         /* Si no encontre gaps ni por delante ni por detras */
118         if ((gap_before.marker == -1) && (gap_after.marker == -1)) {
119                 /* Lo guardo en el archivo al final */
120                 gap_new.marker = marker;
121                 gap_new.freespace = freespace;
122                 fseek(f_fsc,0,SEEK_END);
123                 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
124                 fclose(f_fsc);          
125         }
126         
127         /* Si encuentro un GAP Justo por delante pero no por detras */
128         if ((gap_before.marker != -1) && (gap_after.marker == -1))
129         {
130           /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
131           /* la suma de los espacios libres */    
132           fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
133       gap_new.marker = gap_before.marker;
134           gap_new.freespace = gap_before.freespace + freespace;
135           fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
136           fclose(f_fsc);
137         }
138         
139         /* Si encuentro un GAP Justo por detras pero no por delante */
140         if ((gap_before.marker == -1) && (gap_after.marker != -1))
141         {  
142           /* Me posiciono en el registro que indica dicho gap y lo reescribo con */
143           /* los datos actualizados de offset y espacio */
144           fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
145       gap_new.marker = gap_after.marker - freespace;
146           gap_new.freespace = gap_after.freespace + freespace;
147           fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
148           fclose(f_fsc);
149         }
150         
151         /* Finalmente, si encuentro Justo por delante y por detras..*/
152         if ((gap_before.marker != -1) && (gap_after.marker != -1))
153         { 
154           /* Guardo el nuevo GAP que posee los tres espacios sumados */
155           if (pos_gap_before < pos_gap_after) {
156                 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_before,0);
157                 destination = sizeof(EMUFS_FSC)*pos_gap_after;
158           }
159           else {
160                 fseek(f_fsc,sizeof(EMUFS_FSC)*pos_gap_after,0);
161                 destination = sizeof(EMUFS_FSC)*pos_gap_before;
162           }
163       gap_new.marker = gap_before.marker;
164           gap_new.freespace = gap_before.freespace + freespace + gap_after.freespace;
165           fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
166                 
167           /* Preparo el escenario para la movida de registros */
168           source = destination+sizeof(EMUFS_FSC); /* Salteo el gap que elimino! */
169           fseek(f_fsc,0,SEEK_END);
170           file_size = ftell(f_fsc);
171           reg_count = (file_size - source) / sizeof(EMUFS_FSC);
172           
173           /* Comienzo a mover */
174           while (cant_moved < reg_count) {
175         fseek(f_fsc,source,0);
176         fread(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
177                 fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
178                 fwrite(&gap_new,sizeof(EMUFS_FSC),1,f_fsc);
179                 source += sizeof(EMUFS_FSC);            
180                 ++cant_moved;
181           }
182           fclose(f_fsc);
183           truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
184         }       
185         
186     return 0;
187 }
188
189 /* Elimina un registro GAP del archivo de espacios libres (gaps) */
190 int emufs_fsc_remove_gap(EMUFS *emu, EMUFS_OFFSET marker)
191 {
192         FILE *f_fsc;
193         EMUFS_FSC gap_aux;
194         char name_f_fsc[255];
195     unsigned long source,destination,file_size,reg_count = 0,cant_moved = 0;    
196                 
197         strcpy(name_f_fsc,emu->nombre);
198         strcat(name_f_fsc, EMUFS_FSC_EXT);
199         
200         /* Busco el Gap en el .fsc */
201     if ((f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1; 
202         while ( !feof(f_fsc) ){
203                 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
204                 if ( gap_aux.marker == marker ) break;
205         }
206         
207         /* Preparo el escenario para la movida de registros */
208         fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
209         destination = ftell(f_fsc);
210         source = destination+sizeof(EMUFS_FSC); /* Salteo el gap a eliminar! */
211         fseek(f_fsc,0,SEEK_END);
212         file_size = ftell(f_fsc);
213         reg_count = (file_size - source) / sizeof(EMUFS_FSC);
214                 
215         /* Comienzo a mover */
216         while (cant_moved < reg_count) {
217           fseek(f_fsc,source,0);
218       fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
219           fseek(f_fsc,-sizeof(EMUFS_FSC)*2,SEEK_CUR);
220           fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
221           source += sizeof(EMUFS_FSC);          
222           ++cant_moved;
223         }
224         fclose(f_fsc);
225         truncate(name_f_fsc, file_size - sizeof(EMUFS_FSC));
226         
227         return 0;
228 }
229
230 /* Objetivo: Actualiza un registro de espacio libre de acorde al FType */
231 int emufs_fsc_actualizar(EMUFS *emu, EMUFS_BLOCK_ID marker, EMUFS_FREE freespace)
232 {
233         FILE *f_fsc;
234         EMUFS_FSC reg;
235         char name_f_fsc[255];
236         
237         strcpy(name_f_fsc,emu->nombre);
238         strcat(name_f_fsc, EMUFS_FSC_EXT);
239
240         /*busco el bloque o gap que modifique*/
241         if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1; 
242         while ( !feof(f_fsc) ){
243                 if ( fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
244                 if ( reg.marker == marker ){
245                         reg.freespace = freespace;
246                         fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
247                         fwrite(&reg,sizeof(EMUFS_FSC),1,f_fsc);
248                         break;
249                 }
250         }
251         fclose(f_fsc);
252         return 0;
253 }
254
255 /* Actualiza un registro de gap, en el archivo de Gaps en Disco */
256 int emufs_fsc_actualizar_gap(EMUFS *emu, EMUFS_OFFSET marker, EMUFS_FREE freespace)
257 {
258         FILE *f_fsc;
259         EMUFS_FSC gap_aux;
260         char name_f_fsc[255];
261         
262         strcpy(name_f_fsc,emu->nombre);
263         strcat(name_f_fsc, EMUFS_FSC_EXT);
264
265         /*busco el bloque o gap que modifique*/
266         if ( (f_fsc = fopen(name_f_fsc,"r+")) == NULL) return -1; 
267         while ( !feof(f_fsc) ){
268                 if ( fread(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
269                 if ( gap_aux.marker == marker ){
270                         gap_aux.marker = marker + gap_aux.freespace - freespace;
271                         gap_aux.freespace = freespace;
272                         fseek(f_fsc,-sizeof(EMUFS_FSC),SEEK_CUR);
273                         fwrite(&gap_aux,sizeof(EMUFS_FSC),1,f_fsc);
274                         break;
275                 }
276         }
277         fclose(f_fsc);
278         return 0;
279 }
280
281 /* Me devuelve el ID del bloque u Offset del Gap donde quepa un registro, y guarda en n_freespace el espacio libre actualizado */
282 EMUFS_BLOCK_ID emufs_fsc_buscar_lugar(EMUFS *emu, EMUFS_FREE reg_size, EMUFS_FREE *freespace)
283 {
284         FILE *f_fsc;
285         EMUFS_FSC reg;
286         char name_f_fsc[255];
287         char found = 0;
288         
289         strcpy(name_f_fsc,emu->nombre);
290         strcat(name_f_fsc, EMUFS_FSC_EXT);
291
292         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return EMUFS_NOT_FOUND;
293
294         if ( emu->tam_reg > emu->tam_bloque-sizeof(EMUFS_REG_ID) ){
295                 fseek(f_fsc,0,SEEK_SET);
296                 while(!feof(f_fsc)){
297                         if (fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
298                         if (reg.freespace == emu->tam_bloque) {
299                                 fclose(f_fsc);
300                                 *freespace = reg.freespace;
301                                 return reg.marker;
302                         }
303                 }
304         }       
305         /* Inicializamos la estructura para devolver algun valor en concreto */
306         /* en caso de que no se halle un espacio libre apropiado */
307         while(!feof(f_fsc)){
308                 if (fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1) continue;
309                 if (reg.freespace >= reg_size) {
310                         found = 1;
311                         break;
312                 }
313         }
314         
315         /* Si salio por error o por fin de archivo y no encontro space... */
316         if (!found) {
317           reg.marker = EMUFS_NOT_FOUND;
318           *freespace = emu->tam_bloque; 
319         }
320         else *freespace = reg.freespace;
321         
322         fclose(f_fsc);
323         return reg.marker;
324 }
325
326 /* Devuelve el espacio libre de un Bloque o Gap dado */
327 EMUFS_FREE emufs_fsc_get_fs(EMUFS *emu, EMUFS_BLOCK_ID marker)
328 {
329         FILE *f_fsc;
330         EMUFS_FSC reg;
331         char name_f_fsc[255];
332         
333         strcpy(name_f_fsc,emu->nombre);
334         strcat(name_f_fsc, EMUFS_FSC_EXT);
335
336         /* Busco el Bloque o Gap pedido y obtengo su espacio libre */
337         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
338         while ( !feof(f_fsc) ){
339                 if ( fread(&reg,sizeof(EMUFS_FSC),1,f_fsc) != 1 ) continue;
340                 if ( reg.marker == marker )
341                         break;
342         }
343                 
344         fclose(f_fsc);
345         return reg.freespace;
346 }
347
348 EMUFS_FREE emufs_fsc_get_total_fs(EMUFS *emu)
349 {
350         FILE *f_fsc;
351         EMUFS_FSC reg;
352         char name_f_fsc[255];
353         EMUFS_FREE total;
354         
355         strcpy(name_f_fsc,emu->nombre);
356         strcat(name_f_fsc, EMUFS_FSC_EXT);
357
358         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
359         total = 0;
360         while ( !feof(f_fsc) ){
361                 if ( fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
362                 total += reg.freespace;
363         }
364         fclose(f_fsc);
365         return total;
366 }
367
368 int emufs_fsc_get_max_min_fs(EMUFS *emu, EMUFS_FREE *min, EMUFS_FREE *max)
369 {
370         FILE *f_fsc;
371         EMUFS_FSC reg;
372         char name_f_fsc[255];
373         
374         strcpy(name_f_fsc,emu->nombre);
375         strcat(name_f_fsc, EMUFS_FSC_EXT);
376
377         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
378                 
379         /* Si el file esta vacio, devuelvo valores nulos */
380         fseek(f_fsc,0,SEEK_END);
381         if (ftell(f_fsc) == 0) {
382                 *min = 0;
383                 *max = 0;
384                 return 0;               
385         }
386         else
387         {
388                 /* Busco Min y Max */
389                 *min = ULONG_MAX;
390                 *max = 0;               
391                 fseek(f_fsc,0,SEEK_SET);                
392                 while ( !feof(f_fsc) ){
393                         if ( fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;
394                         if (  reg.freespace < *min )
395                                 *min = reg.freespace;
396                         if ( reg.freespace > *max )
397                                 *max = reg.freespace;
398                 }
399                 fclose(f_fsc);
400                 return 0;               
401         }
402 }
403
404 EMUFS_FREE emufs_fsc_get_media_fs(EMUFS *emu)
405 {
406         FILE *f_fsc;
407         EMUFS_FSC reg;
408         char name_f_fsc[255];
409         EMUFS_FREE total_fs = 0;
410         EMUFS_REG_ID gap_count = 0;
411         
412         strcpy(name_f_fsc,emu->nombre);
413         strcat(name_f_fsc, EMUFS_FSC_EXT);
414
415         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
416         
417         while ( !feof(f_fsc) ){
418                 if ( fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc) != 1) continue;           
419                 total_fs += reg.freespace;
420                 ++gap_count;
421         }
422
423         fclose(f_fsc);
424         
425         if (gap_count > 0) return total_fs/gap_count;
426         else return 0;
427 }
428
429 int emufs_fsc_get_cant_bloques_vacios(EMUFS *emu)
430 {
431         FILE *f_fsc;
432         EMUFS_FSC reg;
433         char name_f_fsc[255];
434         int cant=0;
435         
436         strcpy(name_f_fsc,emu->nombre);
437         strcat(name_f_fsc, EMUFS_FSC_EXT);
438
439         if ( (f_fsc = fopen(name_f_fsc,"r"))==NULL ) return -1;
440         while ( !feof(f_fsc) ){
441                 fread(&reg, sizeof(EMUFS_FSC), 1, f_fsc);
442                 if ( reg.freespace == emu->tam_bloque )
443                         cant++;
444         }
445                 
446         fclose(f_fsc);
447         return cant;
448 }
449
450 int emufs_fsc_truncate(EMUFS* efs, EMUFS_BLOCK_ID blocks)
451 {
452         char name_f_fsc[255];
453
454         strcpy(name_f_fsc, efs->nombre);
455         strcat(name_f_fsc, EMUFS_FSC_EXT);
456         return truncate(name_f_fsc, blocks * sizeof(EMUFS_FSC));
457 }