/*! * \ingroup cache_interface * * Cette fonction invalide le cache, c'est-à -dire le vide de son contenu. * * On synchronise le cache puis tous les blocs sont marqués invalides * (RAZ du flag \c VALID). C'est comme si le cache devenait vide. On invalide * aussi la stratégie. * * \param pcache un pointeur sur le cache à synchroniser * \return le code d'erreur */ Cache_Error Cache_Invalidate(struct Cache *pcache) { int ib; int rcode; /* Synchronisation du cache */ if ((rcode = Cache_Sync(pcache)) != CACHE_OK) return rcode; /* Tous les blocs deviennent invalides */ for (ib = 0; ib < pcache->nblocks; ib++) { struct Cache_Block_Header *pbh = &pcache->headers[ib]; pbh->flags &= ~VALID; } /* Initialisation du pointeur sur le premier bloc libre, cad ici le premier * bloc */ pcache->pfree = pcache->headers; /* La stratégie a peut-être quelque chose à faire */ Strategy_Invalidate(pcache); return CACHE_OK; }
/*! \brief Synchronisation périodique. * * \ingroup cache_internal * * Pour simplifier, elle est réalisée toutes les \c NSYNC opérations de lecture * ou d'écriture. Dans une système réel, elle serait plutôt réalisée * périodiquement dans le temps (toutes les \a T secondes). * * \param pcache un pointeur sur le cache à synchroniser * \return le code d'erreur */ static Cache_Error Do_Sync_If_Needed(struct Cache *pcache) { static int sync_freq = NSYNC; if (--sync_freq == 0) { sync_freq = NSYNC; return Cache_Sync(pcache); } else return CACHE_OK; }
//a terminer Cache_Error Cache_Write(struct Cache *pcache, int irfile, const void *precord){ ibfile =irfile/nrecords; int var =IndexSearch( ibfile, pcache); if( var >-1){ memcpy(pcache->headers[var].data,precord,recordsz); }else{ struct Cache_Block_Header* block =Strategy_Replace_Block(pcache); Cache_Sync(pcache); } }
//! Fermeture (destruction) du cache. Cache_Error Cache_Close(struct Cache *pcache) { Cache_Sync(pcache); Strategy_Close(pcache); fclose(pcache->fp); for(struct Cache_Block_Header *h = pcache->headers; h < (pcache->headers + pcache->nblocks); h++) free(h->data); free(pcache->headers); pcache = NULL; return CACHE_OK; }
//! Lecture (à travers le cache). Cache_Error Cache_Read(struct Cache *pcache, int irfile, void *precord) { if(CheckSync(pcache)) Cache_Sync(pcache); int ibfile = (int)(irfile/pcache->nrecords); struct Cache_Block_Header *cbh = NULL; for(struct Cache_Block_Header *h = pcache->headers; h < (pcache->headers + pcache->nblocks); h++) { if(h->ibfile == ibfile && (h->flags & VALID)) { cbh = h; pcache->instrument.n_hits++; break; } } if(!cbh) { cbh = Strategy_Replace_Block(pcache); if(!cbh) cbh = pcache->headers; if(cbh->flags&MODIF) { fseek(pcache->fp, DADDR(pcache, cbh->ibfile), SEEK_SET); fwrite(cbh->data, pcache->blocksz, 1, pcache->fp); } cbh->ibfile = ibfile; cbh->flags = VALID; fseek(pcache->fp, DADDR(pcache, ibfile), SEEK_SET); fread(cbh->data, pcache->blocksz, 1, pcache->fp); } memcpy(precord, ADDR(pcache, irfile, cbh), pcache->recordsz); pcache->instrument.n_reads++; Strategy_Read(pcache, cbh); return CACHE_OK; }
/*! * \ingroup cache_interface * * Cette fonction ferme et détruit le cache : * - Synchronisation du cache. * - Déallocation des entetes de blocs et des blocs eux-memes. * - Déallocation du nom de fichier. * - Déallocation du cache lui-même * * \param pcache un pointeur sur le cache à fermer * \return le code d'erreur */ Cache_Error Cache_Close(struct Cache *pcache) { int ib; /* Synchronisation */ Cache_Sync(pcache); /* Fermeture de la stratégie */ Strategy_Close(pcache); /* Déallocation des blocks */ for (ib = 0; ib < pcache->nblocks; ib++) free(pcache->headers[ib].data); /* Déallocation des entêtes et du nom de fichier */ free(pcache->headers); free(pcache->file); /* Déallocation du cache lui-même */ free(pcache); return CACHE_OK; }