la gestione delle strutture ad albero git-svn-id: svn://10.65.10.50/trunk@5933 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			149 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| ///////////////////////////////////////////////////////////
 | |
| // Cache
 | |
| ///////////////////////////////////////////////////////////
 | |
| #include "ablib09.h"
 | |
| #define RWCACHE_SIZE 100
 | |
| 
 | |
| // funzione di default: prende una chiave a caso chiave
 | |
| const TString & TRWrecord_cache::getkey2discard()
 | |
| {
 | |
|   THash_object * o=get_some_obj();
 | |
|   CHECK(o,"E' stata chiamata la funzione getkey2discard con la cache vuota");
 | |
|   return o->key();
 | |
| }
 | |
| 
 | |
| //Scarica una parte della cache
 | |
| void TRWrecord_cache::discard(const TString & vittima)
 | |
| {
 | |
|   if (items())  //Usa l'items di TFile_cahe che richiame l'items dell'assoc_array _cache
 | |
|   {
 | |
|     if (_flags.is_key(vittima)) //_flags è un assoc_array di TRWcache, usa is_key di assoc_array
 | |
|     {
 | |
|       const char fl=((TString &)_flags[vittima])[1];
 | |
|       // record modificato o nuovo
 | |
|       int err;
 | |
|       TRectype & rec=(TRectype & )TRecord_cache::get(vittima);
 | |
|       file().curr()=rec;       
 | |
|       if (fl == 'D')
 | |
|       {
 | |
|         err=file().rewrite();
 | |
|         if (err!=NOERR)
 | |
|           error_box("Errore nella riscrittura della cache");
 | |
|       } else {
 | |
|         err=file().write();
 | |
|         if (err!=NOERR)
 | |
|           if (err == _isreinsert)
 | |
|             file().rewrite();
 | |
|           else
 | |
|             error_box("Errore nella scrittura della cache");
 | |
|       }
 | |
|       _flags.remove(vittima);
 | |
| 
 | |
|     }//Se non esiste nel assoc_array di TRWcache
 | |
|     _cache.remove(vittima);
 | |
|   }
 | |
| }
 | |
| 
 | |
| const TRectype& TRWrecord_cache::get(const char* chiave)
 | |
| {
 | |
|   if (items()>=RWCACHE_SIZE)
 | |
|     discard(getkey2discard());
 | |
|   const TRectype & rec=TRecord_cache::get(chiave);
 | |
|   if (io_result() != NOERR)
 | |
|   { 
 | |
|     // record non trovato: è nuovo 
 | |
|     _flags.add(chiave,new TString("N"));
 | |
|   }
 | |
|   return rec;
 | |
| }
 | |
| 
 | |
| void TRWrecord_cache::put(const TRectype &r)
 | |
| {
 | |
|   test_firm();
 | |
| 
 | |
|   TToken_string cachekey;
 | |
|   if (!r.empty())
 | |
|   {
 | |
|     const RecDes* recd = r.rec_des();    // Descrizione del record della testata
 | |
|     const KeyDes& kd = recd->Ky[key_number()-1];    // Elenco dei campi della chiave
 | |
|     for (int i = file().tab() ? 1: 0; i < kd.NkFields; i++)   // Riempie la chiave selezionata
 | |
|     {                        
 | |
|       const int nf = kd.FieldSeq[i] % MaxFields;
 | |
|       const RecFieldDes& rf = recd->Fd[nf];  
 | |
|       cachekey.add(r.get(rf.Name));
 | |
|     }
 | |
|   } 
 | |
| 
 | |
|   TObject* obj = _cache.objptr(cachekey);
 | |
| 
 | |
|   if (obj != NULL)
 | |
|   {
 | |
|     // esiste in cache ; tenta di settare il flag a "D"irty; se il flag esiste già è a
 | |
|     TRectype & rec=(TRectype &)*obj;
 | |
|     rec=r;
 | |
|     _flags.add(cachekey , new TString("D"));
 | |
|   } else {
 | |
|     // non esiste in cache 
 | |
|     obj = rec2obj(r);
 | |
|     _cache.add(cachekey, obj);
 | |
|     // qui assume che non esista nemmeno su file, perciò sia "N"uovo; al flush correggerà l'errore
 | |
|     _flags.add(cachekey , new TString("N"));
 | |
|   }
 | |
|   if (items()>=RWCACHE_SIZE)
 | |
|     discard(getkey2discard());
 | |
| }
 | |
| 
 | |
| //Vuota una cache
 | |
| void TRWrecord_cache::clear()
 | |
| {
 | |
|   while (items()>0)
 | |
|   {
 | |
|     const TString & vittima=getkey2discard();
 | |
|     if (_flags.is_key(vittima))
 | |
|       _flags.remove(vittima);
 | |
|     _cache.remove(vittima);
 | |
|   }    
 | |
| }
 | |
| 
 | |
| //Forza la scrittura sulla cache
 | |
| void TRWrecord_cache::flush()
 | |
| {           
 | |
|   while (items()>0)
 | |
|   { 
 | |
|     discard(TRWrecord_cache::getkey2discard());
 | |
|   }
 | |
| }
 | |
| 
 | |
| THash_object * TRWrecord_cache::get_some_obj()
 | |
| {
 | |
|   if (items()==0) //Usa l'items() di TFilecache fa items() di un assoc_array _cahce
 | |
|     return NULL;
 | |
|   THash_object * o;
 | |
|   while ((o=_cache.get_hashobj()) == NULL) ;  //Ritorna l'oggetto e la relativa chiave dell'assoc_array _cache
 | |
|   return o;
 | |
| }
 | |
|                 
 | |
| //Costruttori vari                
 | |
| TRWrecord_cache::TRWrecord_cache(TLocalisamfile *f, int key, bool lock)
 | |
|   :TRecord_cache(f,key)
 | |
| {
 | |
|   if (lock)
 | |
|     file().lock();
 | |
| }
 | |
| 
 | |
| 
 | |
| TRWrecord_cache::TRWrecord_cache(int num, int key, bool lock)
 | |
|   :TRecord_cache(num,key)
 | |
| {
 | |
|   if (lock)
 | |
|     file().lock();
 | |
| }
 | |
| 
 | |
| 
 | |
| TRWrecord_cache::~TRWrecord_cache() 
 | |
| {
 | |
|   flush();
 | |
| }
 | |
| 
 | |
| 
 |