source: Sophya/trunk/FrEROS/AnaLC/filecache.c@ 3619

Last change on this file since 3619 was 3308, checked in by ansari, 18 years ago

Creation du module AnaLC (lecture suivi EROS avec SOPHYA) dans la base
SOPHYA - cmv+reza 22/08/2007

  • Property svn:executable set to *
File size: 11.0 KB
Line 
1#include <unistd.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "machdefs.h"
6
7#ifndef IBMVM
8#include <sys/types.h>
9#include <unistd.h>
10#endif
11
12#include "filecache.h"
13
14#ifdef RFIO
15#include <shift.h>
16#endif
17
18#ifdef __mac__
19#include <stat.h>
20#endif
21
22/*
23++
24 Module Buffered I/O (C)
25 Lib fsv
26 include filecache.h
27
28 Les fonctions décrites ci-dessous permettent de lire et d'écrire
29 des fichiers avec une gestion de mémoire tampon, afin d'optimiser
30 le débit d'entrée-sortie en cas d'utilisation lourde du positionnement
31 dans le fichier (seek()). L'interface est similaire à celle des
32 fonctions d'entrée sortie standard C ("fopen(...)", "fread(...)", ...).
33 Au moment de l'ouverture du fichier (par zfopen()),
34 une liste chainée de zones mémoire, (des pages)
35 est créé. Ces pages sont destinées a contenir une
36 image mémoire des zones accédées du fichier au moment
37 des opérations de lecture et d'écriture, réduisant
38 ainsi le nombre des accés effectifs au fichier disque.
39 La taille et le nombre de page allouées sont contrôlés par
40 l'utilisateur.
41--
42*/
43
44static int zf_prtlev = 0;
45/* Nouvelle-Fonction */
46void zfSetPrtLevel(int lev)
47{
48zf_prtlev = lev;
49}
50
51int pgread(FILECACHE *fcp, long fr, long n, char *buff);
52int pgwrite(FILECACHE *fcp, long fr, long n, char *buff);
53
54/*
55++
56FILECACHE *zfopen(char *flnm, char *mode, int npg, int pgsiz)
57 Ouverture du fichier "flnm", en mode lecture seule ou
58 lecture-écriture. "npg" pages de tailles "pgsiz" sont
59 allouées pour la mémoire tampon. Les caractères "rw+"
60 peuvent être spécifié pour "mode". Si "npg <= 0",
61 les fonctions standard "fseek()", "fread()" et "fwrite()"
62 sont utilisées.
63
64void zfclose( FILECACHE *fcp )
65 Fermeture du fichier. Il est impératif d'appeler zfclose()
66 si le fichier a été ouvert en écriture.
67
68void zfSetPrtLevel(int lev)
69 Modification du niveau d'impression pour le debug.
70 si "lev > 2" des statistiques concernant l'utilisation
71 de la mémoire tampon sont imprimées à la fermeture du fichier.
72--
73*/
74
75
76
77/* Nouvelle-Fonction */
78FILECACHE *zfopen(char *flnm, char *mode, int npg, int pgsiz)
79
80{
81FILE *fip;
82FILECACHE *fcp;
83int i,j;
84DSKPAGE *first, *cur, *prev;
85
86
87if ( (fip=fopen(flnm,mode)) == NULL )
88 {
89 puts("zfopen_Erreur - Erreur fopen !");
90 return(NULL);
91 }
92
93
94if ( (fcp=malloc(sizeof(FILECACHE))) == NULL )
95 {
96 fclose(fip);
97 puts("zfopen_Erreur - Erreur malloc(fcp) !");
98 return(NULL);
99 }
100
101if ( npg < 0 ) { npg = DEF_NPAGE ; pgsiz = DEF_PGSIZE ; }
102
103fcp->fip = fip;
104
105#if defined(IBMVM)
106fcp->fidesc = -1;
107#elif defined(HPUX)
108fcp->fidesc = (int)fip->__fileH*256+(int)fip->__fileL;
109#elif defined(__MWERKS__)
110//fcp->fidesc = (int)fip->_Handle; // ANSI ancien
111fcp->fidesc = (int)fip->handle; // MSL
112#elif defined(Linux)
113fcp->fidesc = (int)fip->_fileno;
114#else
115fcp->fidesc = (int)fip->_file;
116#endif
117
118fcp->fpos = 0;
119fcp->nread = fcp->nwrite = 0;
120fcp->totrd = fcp->totwr =0;
121fseek(fip,0,SEEK_END);
122fcp->fsz = ftell(fip);
123fseek(fip,0,SEEK_SET);
124
125fcp->rwfg = 0;
126for(i=0; i<strlen(mode); i++)
127 if ( ( *(mode+i) == 'w' ) || ( *(mode+i) == '+' ) ) fcp->rwfg = 1;
128
129fcp->memode = 0;
130fcp->first = fcp->last = NULL;
131fcp->pages = NULL;
132fcp->npage = fcp->pgsize = 0;
133
134if (npg <= 0) return(fcp); /* Si pas d'option caching */
135
136if (pgsiz < MIN_PGSIZE) pgsiz = MIN_PGSIZE;
137if (npg < MIN_NPAGE) npg = MIN_NPAGE;
138
139fcp->memode = 1;
140fcp->npage = npg;
141fcp->pgsize = pgsiz;
142
143if ( ( first = (DSKPAGE *)malloc(npg*sizeof(DSKPAGE)) ) == NULL )
144 {
145 fclose(fip); free(fcp);
146 puts("zfopen_Erreur: Pb malloc(DSKPAGE) !");
147 return(NULL);
148 }
149
150prev = NULL;
151cur = first-1;
152for(i=0; i<npg; i++)
153 {
154 cur++;
155 cur->wrfg = 0;
156 cur->pgno = -1;
157 if ( (cur->page=malloc(pgsiz)) == NULL)
158 {
159 for(j=0; j<i; j++)
160 free((first + j)->page);
161 free(first); free(fcp);
162 fclose(fip);
163 return(NULL);
164 }
165 memset( cur->page, pgsiz, '\0');
166 cur->next = cur+1;
167 cur->prev = prev;
168 prev = cur;
169 }
170
171cur->next = NULL;
172fcp->last = cur;
173fcp->first = first;
174fcp->pages = first;
175
176if (zf_prtlev > 5)
177 {
178 printf("zfopen_Debug: NPage= %d , PgSize= %d \n", npg, pgsiz);
179 cur = fcp->first;
180 for (i=0; i<npg; i++)
181 {
182 printf("Pg[%d] *DskPg = %lx *page= %lx *Next= %lx \n",
183 (i+1), (unsigned long)cur, (unsigned long)cur->page, (unsigned long)cur->next);
184 cur = cur->next;
185 }
186 }
187
188return(fcp);
189}
190
191
192
193/* Nouvelle-Fonction */
194void zfclose( FILECACHE *fcp )
195{
196float effr,effw;
197DSKPAGE *cur;
198int_4 pgsiz;
199long int fp;
200
201if (fcp == NULL) return;
202
203
204pgsiz = fcp->pgsize;
205cur = fcp->first;
206while (cur != NULL)
207 {
208 if ( cur->wrfg && fcp->rwfg )
209 {
210 fp = cur->pgno*fcp->pgsize;
211#ifdef IBMVM
212 fseek(fcp->fip, fp, SEEK_SET);
213 fwrite(cur->page, 1, pgsiz, fcp->fip);
214#else
215 lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
216 write(fcp->fidesc, cur->page, pgsiz);
217#endif
218 fcp->nwrite ++;
219 }
220 free(cur->page);
221 cur = cur->next;
222 }
223
224if (zf_prtlev > 2)
225 {
226 if (fcp->nread > 0)
227 effr = (float)(fcp->totrd)/(float)(fcp->nread*pgsiz);
228 else effr = 1.0;
229 if (fcp->nwrite > 0)
230 effw = (float)(fcp->totwr)/(float)(fcp->nwrite*pgsiz);
231 else effw = 1.0;
232 puts(" ================= Statistiques Memoire Cache =================");
233 printf(" NPage= %d PgSize= %d \n", fcp->npage, fcp->pgsize);
234 printf(" PgRead= %d TotRd= %ld TotRd/PgRead= %g \n",
235 fcp->nread, fcp->totrd, effr);
236 printf(" PgWrite= %d TotWr= %ld TotWr/PgWrite= %g \n",
237 fcp->nwrite, fcp->totwr, effw);
238 puts(" ==============================================================");
239 }
240
241/* fcp->first a tourne et ne pointe plus vers la 1ere structure des DSKPAGES* */
242free(fcp->pages);
243fclose(fcp->fip);
244free(fcp);
245
246return;
247
248}
249
250/*
251++
252int zfseek( FILECACHE *fcp, long int offset, int fg)
253 Positionnement dans le fichier. "fg" peut valoir
254 "SEEK_SET", "SEEK_CUR", "SEEK_END", pour
255 un positionnement avec décalage "offset" à partir
256 du début de fichier, de la position courante, ou
257 de la fin du fichier.
258
259size_t zfread( void *buff, size_t size, size_t nitems, FILECACHE *fcp)
260 Lecture à partir de la position courante.
261
262size_t zfwrite( void *buff, size_t size, size_t nitems, FILECACHE *fcp)
263 Ecriture à partir de la position courante.
264--
265*/
266
267/* Nouvelle-Fonction */
268int zfseek( FILECACHE *fcp, long int offset, int fg)
269{
270long int newpos;
271
272if (fcp == NULL) return(-2);
273if ( !fcp->memode ) return ( fseek(fcp->fip, offset, fg) );
274
275newpos = offset;
276if (fg == SEEK_SET) newpos = offset;
277if (fg == SEEK_CUR) newpos = fcp->fpos + offset;
278if (fg == SEEK_END) newpos = fcp->fsz - offset;
279
280if ( newpos < 0 ) return(-1);
281if ( !fcp->rwfg && (newpos >= fcp->fsz) ) return(-1);
282fcp->fpos = newpos;
283return(0);
284
285}
286
287
288
289/* Nouvelle-Fonction */
290size_t zfread( void *buff, size_t size, size_t nitems, FILECACHE *fcp)
291{
292long int m,n;
293long int fr,nr;
294
295
296if (fcp == NULL) return(0);
297if ( !fcp->memode ) return ( fread(buff, size, nitems, fcp->fip) );
298
299#ifdef DEBUG_FCACHE
300printf(" Debug_zfread pos,size,nitem= %d %d %d\n",fcp->fpos,size,nitems);
301#endif
302
303m = 0; n = size*nitems;
304if ( fcp->fpos+n > fcp->fsz ) n = fcp->fsz-fcp->fpos;
305if ( n <= 0) return(0);
306fr = fcp->fpos;
307
308fcp->totrd += n; nr = n;
309
310while ((m < n) && (nr > 0))
311 {
312#ifdef DEBUG_FCACHE
313 printf(" Debug_zfread_2 fr,n,m= %d %d %d\n",fr,n,m);
314#endif
315 nr = pgread(fcp,fr,(n-m), ((char *)buff)+m);
316 m += nr; fr += nr;
317 }
318
319fcp->fpos += m;
320
321return(m);
322}
323
324
325/* Nouvelle-Fonction */
326int pgread(FILECACHE *fcp, long fr, long n, char *buff)
327{
328long int pgnum, pg;
329long int off, nr;
330
331long int fp;
332DSKPAGE *cur;
333
334pgnum = fr / fcp->pgsize;
335
336/* On regarde si la page est en memoire */
337
338pg = -1;
339cur = fcp->first;
340while (cur != NULL)
341 {
342 if (cur->pgno < 0) break;
343 if (cur->pgno == pgnum) { pg = pgnum; break; }
344 cur = cur->next;
345 }
346
347
348/* On la lit si elle n'y est pas */
349if ( pg < 0)
350 {
351 cur = fcp->last;
352/* On reecrit la derniere page si necessaire */
353 if ( cur->wrfg && fcp->rwfg )
354 {
355 fp = cur->pgno*fcp->pgsize;
356#ifdef IBMVM
357 fseek(fcp->fip, fp, SEEK_SET);
358 fwrite(cur->page, 1, fcp->pgsize, fcp->fip);
359#else
360 lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
361 write(fcp->fidesc, cur->page, fcp->pgsize);
362#endif
363 fcp->nwrite ++;
364 }
365
366 fp = pgnum*fcp->pgsize;
367#ifdef IBMVM
368 fseek(fcp->fip, fp, SEEK_SET);
369 fread(cur->page, 1, fcp->pgsize, fcp->fip);
370#else
371 lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
372 read(fcp->fidesc, cur->page, fcp->pgsize);
373#endif
374 cur->pgno = pgnum;
375 cur->wrfg = 0;
376 fcp->nread ++;
377 }
378
379/* On reordonne les pages */
380if ( cur != fcp->first )
381 {
382 if ( cur == fcp->last )
383 { fcp->last = cur->prev; (fcp->last)->next = NULL; }
384 else
385 { (cur->prev)->next = cur->next; (cur->next)->prev = cur->prev; }
386
387 (fcp->first)->prev = cur;
388 cur->next = fcp->first;
389 cur->prev = NULL;
390 fcp->first = cur;
391 }
392
393/* Copie ds buffer utilisateur */
394off = fr - pgnum*fcp->pgsize;
395if ( (nr=fcp->pgsize-off) > n ) nr = n;
396memcpy(buff, (cur->page)+off, nr);
397
398return(nr);
399}
400
401
402
403/* Nouvelle-Fonction */
404size_t zfwrite( void *buff, size_t size, size_t nitems, FILECACHE *fcp)
405{
406long int m,n;
407long int fr,nw;
408
409
410if (fcp == NULL) return(-1);
411if ( !fcp->rwfg ) return(-2);
412if ( !fcp->memode ) return ( fwrite(buff, size, nitems, fcp->fip) );
413
414
415m = 0; n = size*nitems;
416if ( n <= 0) return(0);
417
418fr = fcp->fpos;
419fcp->totwr += n; nw = n;
420
421while ((m < n) && (nw > 0))
422 {
423 nw = pgwrite(fcp,fr,(n-m), ((char*)buff)+m);
424 m += nw; fr += nw; }
425
426fcp->fpos += m;
427if (fcp->fpos >= fcp->fsz) fcp->fsz = fcp->fpos+1;
428
429return(m);
430}
431
432
433/* Nouvelle-Fonction */
434
435int pgwrite(FILECACHE *fcp, long fr, long n, char *buff)
436
437{
438long int pgnum, pg;
439long int off, nw;
440
441long int fp;
442DSKPAGE *cur;
443
444pgnum = fr / fcp->pgsize;
445
446/* On regarde si la page est en memoire */
447
448pg = -1;
449cur = fcp->first;
450while (cur != NULL)
451 {
452 if (cur->pgno < 0) break;
453 if ( cur->pgno == pgnum) { pg = pgnum; break; }
454 cur = cur->next;
455 }
456
457
458/* On la lit si elle n'y est pas */
459if ( pg < 0)
460 {
461
462 cur = fcp->last;
463/* On reecrit la derniere page si necessaire */
464 if ( cur->wrfg && fcp->rwfg)
465 {
466 fp = cur->pgno*fcp->pgsize;
467#ifdef IBMVM
468 fseek(fcp->fip, fp, SEEK_SET);
469 fwrite(cur->page, 1, fcp->pgsize, fcp->fip);
470#else
471 lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
472 write(fcp->fidesc, cur->page, fcp->pgsize);
473#endif
474 fcp->nwrite ++;
475 }
476
477 fp = pgnum*fcp->pgsize;
478 if ( (fp + fcp->pgsize) >= fcp->fsz ) /* remise a zero de la page */
479 memset( cur->page, fcp->pgsize, '\0');
480#ifdef IBMVM
481 fseek(fcp->fip, fp, SEEK_SET);
482 fread(cur->page, 1, fcp->pgsize, fcp->fip);
483#else
484 lseek(fcp->fidesc, (off_t)fp, SEEK_SET);
485 read(fcp->fidesc, cur->page, fcp->pgsize);
486#endif
487 cur->pgno = pgnum;
488 cur->wrfg = 0;
489 fcp->nread ++;
490 }
491
492/* On reordonne les pages */
493if ( cur != fcp->first )
494 {
495 if ( cur == fcp->last )
496 { fcp->last = cur->prev; (fcp->last)->next = NULL; }
497 else
498 { (cur->prev)->next = cur->next; (cur->next)->prev = cur->prev; }
499
500 (fcp->first)->prev = cur;
501 cur->next = fcp->first;
502 cur->prev = NULL;
503 fcp->first = cur;
504 }
505
506/* Copie ds buffer utilisateur */
507off = fr - pgnum*fcp->pgsize;
508if ( (nw=fcp->pgsize-off) > n ) nw = n;
509memcpy((cur->page)+off, buff, nw);
510cur->wrfg = 1;
511
512return(nw);
513}
Note: See TracBrowser for help on using the repository browser.