#include #include "svlib09.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(); } void TRWrecord_cache::discard(const TString & vittima) { if (items()) { if (_flags.is_key(vittima)) { const char fl=((TString &)_flags[vittima])[0]; // 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) err=file().write(); 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); } _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,TString4("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]; const TString & fval = r.get(rf.Name); cachekey.add(fval); } } else warning_box("adding an empty record"); 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 , TString4("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()); } void TRWrecord_cache::clear() { while (items()>0) { const TString & vittima=getkey2discard(); if (_flags.is_key(vittima)) _flags.remove(vittima); _cache.remove(vittima); } } void TRWrecord_cache::flush() { while (items()>0) discard(TRWrecord_cache::getkey2discard()); } THash_object * TRWrecord_cache::get_some_obj() { if (items()==0) return NULL; THash_object * o; while ((o=_cache.get_hashobj()) == NULL) ; return o; } 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(); }