campo-sirio/sv/svlib09.cpp
augusto 3445312adb Scorporata la classe TRWcache dalla libreria normale delle statistiche
I files svlib09.cpp e svlib09.h permettono la gestione delle cache
di lettura e SCRITTURA che operano su un Localisamfile

Il metodo più importante è "put(rectype)", simmetrico di get() delle
cache normali.

La cache ha un algoritmo di discarding semplice (sbatte via una chiave a caso)
ma è possibile imporre una politica particolare mediante la ridefinizione
della funzione virtuale getkey2discard()


git-svn-id: svn://10.65.10.50/trunk@5782 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-12-23 11:38:42 +00:00

148 lines
3.2 KiB
C++
Executable File

//#include <prefix.h>
//#include <progind.h>
#include <recarray.h>
//#include "svlib01.h"
#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])[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);
}
_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());
}
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();
}