Modifiche per geenrare l'oggetto absaldo per derivazione

git-svn-id: svn://10.65.10.50/trunk@5939 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
augusto 1998-01-14 17:49:01 +00:00
parent dca3e18971
commit d5cc1b62e2
2 changed files with 356 additions and 207 deletions

View File

@ -9,21 +9,111 @@
/**************************************************************************************************/ /**************************************************************************************************/
// TAnalisi_bil // TAnalisi_bil
/**************************************************************************************************/ /**************************************************************************************************/
TAlbero_AB::TAlbero_AB(int filenum)
:TRectype(filenum)
{
}
int TAlbero_AB::write(TBaseisamfile &analisi) const
{
int err = TRectype::write(analisi);
if (err==NOERR)
{
commit_body();
}
if (err)
CHECK (FALSE,"Errore di scrittura del record sull'isamfile");
return err;
}
int TAlbero_AB::rewrite(TBaseisamfile &analisi) const
{
int err = TRectype::rewrite(analisi);
if (err==NOERR)
{
commit_body();
}
if (err)
CHECK (FALSE,"Errore di scrittura del record sull'isamfile");
return err;
}
//Leggo la "testata" del record
int TAlbero_AB::read(TBaseisamfile& analisi, word isop, word lockop)
{
int err=TRectype::read(analisi, isop, lockop);
if (err==NOERR)
read_body(FALSE);
return err;
}
//Leggo la testata del record basandomi sulla posizione
int TAlbero_AB::readat(TBaseisamfile& analisi, TRecnotype nrec, word lockop)
{
int err=TRectype::readat(analisi, nrec, lockop);
if (err==NOERR)
read_body(FALSE);
return err;
}
int TAlbero_AB::remove(TBaseisamfile& f) const
{
/*Abilitare questa parte solo per effettuare un debug della delete_node
// anche se messa in questa posizione, la chiamata non ha senso
TLocalisamfile lf(LF_RELANA);
TNumeric_id id;
id = 17;
_inter_tree->delete_node(id);
int errc = commit_body(lf);
if (errc != NOERR)
{
message_box("Errore nell'aggiornameno del file dati");
//return errc;
}
return 0;
*/
//*Abilitare solo questa parte per il test della remove_tree
_inter_tree->delete_tree();
int errc = commit_body();
if (errc != NOERR)
{
message_box("Errore nell'aggiornameno del file dati");
//return errc;
}
int err = TRectype::remove(f);
return err;
}
void TAlbero_AB::zero()
{
_inter_tree->zero();
TRectype::zero() ;
}
/**************************************************************************************************/
// TAnalisi_bil
/**************************************************************************************************/
TAnalisi_bil::TAnalisi_bil() TAnalisi_bil::TAnalisi_bil()
:TRectype(LF_ANALISI) :TAlbero_AB(LF_ANALISI)
{ {
_voci = new TLocalisamfile(LF_VOCI); _voci = new TLocalisamfile(LF_VOCI);
_analisi= new TLocalisamfile(LF_ANALISI); _analisi= new TLocalisamfile(LF_ANALISI);
_relaz = NULL; _relaz = NULL;
_ana = NULL; _ana = NULL;
_inter_tree = new TInsert_albero(); _inter_tree = new TLocal_relana3();
_newrec = new TRectype(LF_RELANA); _newrec = new TRectype(LF_RELANA);
} }
TAnalisi_bil::~TAnalisi_bil() TAnalisi_bil::~TAnalisi_bil()
{ {
delete _inter_tree ;
delete _voci; delete _voci;
delete _ana; delete _ana;
delete _relaz; delete _relaz;
@ -31,81 +121,32 @@ TAnalisi_bil::~TAnalisi_bil()
delete _newrec; delete _newrec;
} }
//Estraggo un nodo: in ingresso ho un id e il codice della tabella; void TAnalisi_bil::put_headkey(TRectype &rec) const
//in output ho il record e le informazioni per sapere cosa fare di quel record {
TRectype TInsert_albero::extract_node(const TString &codtab,TNumeric_id &id, TString &status) rec.put(ABAN_CODAN, get(ABAN_CODAN));
{
TToken_string key = codtab;
TRectype rec(LF_RELANA);
THash_object *row_status;
if (id == ID_NULLO)
{ //Gestione interna
_status_node.restart();
row_status = _status_node.get_hashobj();
status = (TString&)row_status->obj();
id = (TNumeric_id)row_status->key();
}
else
{
status = *(TString*)_status_node.objptr(id.string());
}
//Posso accedere alla cache (con la get) solo se il nodo non
//è stato rimosso: se il nodo è stato rimosso, non sarà presente
//nella cache, e quindi la get di un nodo che non esiste è un record
//vuoto; questo record vuoto causerà errori nel momento in cui chiamerò
//la flush per il distruttore; devo quindi evitare questo
//caso l'utilizzo della get
if (status != NODO_RIMOSSO)
{
key.add(id.string()); //La chiave è completamente ricostruita per la ricerca sulla cache
rec = _ana_cache->get(key); //passo la chiave (formata da codtab e id) e ritorna il rectype
}
else
{ //Riempio manualmente il record che deve essere rimosso: inserisco solo la chiave
rec.put(ABRA_CODAN,codtab);
rec.put(ABRA_ID,id.string());
}
//A questo punto il record è completo e so già quale operazione devo compierci sopra
//Questa parte serve per gestire l'assoc_array degli status
if ((rec.empty()) && (status != NODO_RIMOSSO))
{ //Chiave non trovata: la chiave ricercata non è presente nella cache
fatal_box("Errore nella lettura della cache o nella costruzione del record.");
}
_status_node.remove(id.string());
return rec; //Ritorno un Trectype e passo la stauts node
} }
int TAnalisi_bil::write(TBaseisamfile &analisi) const
{
TLocalisamfile relana(LF_RELANA);
int err = commit_body(relana);
if (err)
CHECK (FALSE,"Errore di scrittura del record sull'isamfile");
return err;
}
//Scrive tutto il contenuto della cache sull'isamfile, aggiungendo, modificando //Scrive tutto il contenuto della cache sull'isamfile, aggiungendo, modificando
//o rimuovendo i nodi necessari //o rimuovendo i nodi necessari
int TAnalisi_bil::commit_body(TLocalisamfile &relana) const
int TAlbero_AB::commit_body() const
{ {
TRectype rec(LF_RELANA); TRectype rec(_inter_tree->current().num());
TLocalisamfile filebody(rec.num());
TString status; TString status;
//Estraggo un nodo per volta basandomi sull'assoc_array degli status //Estraggo un nodo per volta basandomi sull'assoc_array degli status
while (_inter_tree->status_node_items() > 0) while (_inter_tree->dirty_nodes() > 0)
{ {
TNumeric_id id; TNumeric_id id;
int prova = _inter_tree->status_node_items(); int prova = _inter_tree->dirty_nodes();
rec= _inter_tree->extract_node(get(ABAN_CODAN), id, status);
id=ID_NULLO;
rec= _inter_tree->extract_dirtynode(id, status);
put_headkey(rec);
//Ho un rectype e uno status node //Ho un rectype e uno status node
if (status == NODO_AGGIUNTO) if (status == NODO_AGGIUNTO)
{ {
if (relana.curr().empty()) if (filebody.curr().empty())
{ //Se il cursor di relana è posizionato in modo errato: { //Se il cursor di relana è posizionato in modo errato:
//lo sistemo sull'ultimo record del file //lo sistemo sull'ultimo record del file
//DOMANDA: - Perchè ??? //DOMANDA: - Perchè ???
@ -116,22 +157,22 @@ int TAnalisi_bil::commit_body(TLocalisamfile &relana) const
// In tutti gli altri casi (quando l'ultima azione è stata una write o una rewrite o una remove di un record // In tutti gli altri casi (quando l'ultima azione è stata una write o una rewrite o una remove di un record
// che non sia l'ultimo) questo problema non esiste. // che non sia l'ultimo) questo problema non esiste.
//RISPOSTA ESATTA: - Bho !!! //RISPOSTA ESATTA: - Bho !!!
relana.last(); filebody.last();
} }
int err = relana.write(rec); int err = filebody.write(rec);
if (err != NOERR) if (err != NOERR)
return err; return err;
} }
if (status == NODO_MODIFICATO) if (status == NODO_MODIFICATO)
{ {
int err = relana.rewrite(rec); int err = filebody.rewrite(rec);
if (err != NOERR) if (err != NOERR)
return err; return err;
} }
if (status == NODO_RIMOSSO) if (status == NODO_RIMOSSO)
{ {
relana.read(rec); //Devo leggere sul file per posizionare il cursore: stesso motivo di prima filebody.read(rec); //Devo leggere sul file per posizionare il cursore: stesso motivo di prima
int err = relana.remove(rec); int err = filebody.remove(rec);
if (err != NOERR) if (err != NOERR)
return err; return err;
} }
@ -140,24 +181,6 @@ int TAnalisi_bil::commit_body(TLocalisamfile &relana) const
return NOERR; return NOERR;
} }
//Leggo la "testata" del record
int TAnalisi_bil::read(TBaseisamfile& analisi, word isop, word lockop)
{
int err=TRectype::read(analisi, isop, lockop);
if (err==NOERR)
read_body(FALSE);
return err;
}
//Leggo la testata del record basandomi sulla posizione
int TAnalisi_bil::readat(TBaseisamfile& analisi, TRecnotype nrec, word lockop)
{
int err=TRectype::readat(analisi, nrec, lockop);
if (err==NOERR)
read_body(FALSE);
return err;
}
//Leggo il "corpo" del record //Leggo il "corpo" del record
int TAnalisi_bil::read_body(bool lock_struct ) int TAnalisi_bil::read_body(bool lock_struct )
{ {
@ -189,44 +212,6 @@ int TAnalisi_bil::read_body(bool lock_struct )
} }
return 0; return 0;
} }
int TAnalisi_bil::remove(TBaseisamfile& f) const
{
/*Abilitare questa parte solo per effettuare un debug della delete_node
// anche se messa in questa posizione, la chiamata non ha senso
TLocalisamfile lf(LF_RELANA);
TNumeric_id id;
id = 17;
_inter_tree->delete_node(id);
int errc = commit_body(lf);
if (errc != NOERR)
{
message_box("Errore nell'aggiornameno del file dati");
//return errc;
}
return 0;
*/
//*Abilitare solo questa parte per il test della remove_tree
TLocalisamfile lf(LF_RELANA);
_inter_tree->delete_tree();
int errc = commit_body(lf);
if (errc != NOERR)
{
message_box("Errore nell'aggiornameno del file dati");
//return errc;
}
int err = TRectype::remove(f);
return err;
}
void TAnalisi_bil::zero()
{
_inter_tree->zero();
TRectype::zero() ;
}
//Naviga l'albero delle relazioni //Naviga l'albero delle relazioni
void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNumeric_id & id_prec,const TNumeric_id & id_padre) void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNumeric_id & id_prec,const TNumeric_id & id_padre)
{ {
@ -360,30 +345,99 @@ bool TAnalisi_bil::TArray_fratelli::used(TObject *o)
} }
/**************************************************************************************************/ /**************************************************************************************************/
// TInsert_albero // TAlbero_locale
/**************************************************************************************************/ /**************************************************************************************************/
TInsert_albero::TInsert_albero() TLocal_relana3::TLocal_relana3() :
TAlbero_locale(LF_RELANA)
{
}
TLocal_relana3::~TLocal_relana3()
{}
TLocal_balance3::TLocal_balance3() :
TAlbero_locale(LF_MOVDETT)
{
}
TLocal_balance3::~TLocal_balance3()
{}
TAlbero_locale::TAlbero_locale(int filenum)
{ {
// versione definitiva: // versione definitiva:
// _currnode = new TRectype(LF_RELANA); // _currnode = new TRectype(filenum);
// _ana_cache = new TRWrecord_cache(new TIsamtempfile(LF_RELANA,"",TRUE,TRUE)); // _local_cahe = new TRWrecord_cache(new TIsamtempfile(filenum,"",TRUE,TRUE));
// debug mods: // debug mods:
_currnode = new TRectype(LF_RELANA); _currnode = new TRectype(filenum);
_f= new TIsamtempfile(LF_RELANA,"/com/relana",FALSE,FALSE); if (filenum==LF_RELANA)
_ana_cache = new TRWrecord_cache(_f); _f= new TIsamtempfile(filenum,"/com/relana",FALSE,FALSE);
else
_f= new TIsamtempfile(filenum,"",FALSE,FALSE);
_local_cahe = new TRWrecord_cache(_f);
//zero(); // resetta l'albero locale //zero(); // resetta l'albero locale
} }
TInsert_albero::~TInsert_albero() TAlbero_locale::~TAlbero_locale()
{ {
delete _ana_cache; delete _local_cahe;
delete _f; delete _f;
} }
//Estraggo un nodo: se specifico l'id in ingresso estrae il nodo con quell'id;
//altrimenti ne sceglie uno a caso tra quelli "dirty"
//in output ho il record e le informazioni per sapere cosa fare di quel record
TRectype TAlbero_locale::extract_dirtynode(TNumeric_id &id, TString &status)
{
TToken_string key = get_headkey();
TRectype rec(current());
THash_object *row_status;
if (id == ID_NULLO)
{ //Gestione interna
_status_node.restart();
row_status = _status_node.get_hashobj();
status = (TString&)row_status->obj();
id = (TNumeric_id)row_status->key();
}
else
{
status = *(TString*)_status_node.objptr(id.string());
}
//Posso accedere alla cache (con la get) solo se il nodo non
//è stato rimosso: se il nodo è stato rimosso, non sarà presente
//nella cache, e quindi la get di un nodo che non esiste è un record
//vuoto; questo record vuoto causerà errori nel momento in cui chiamerò
//la flush per il distruttore; devo quindi evitare questo
//caso l'utilizzo della get
if (status != NODO_RIMOSSO)
{
key.add(id.string()); //La chiave è completamente ricostruita per la ricerca sulla cache
rec = _local_cahe->get(key); //passo la chiave (formata da codtab e id) e ritorna il rectype
}
else
{ //Riempio manualmente il record che deve essere rimosso: inserisco solo la chiave
//rec.put(ABRA_CODAN, ??? );
rec.put(ABRA_ID,id.string());
}
//A questo punto il record è completo e so già quale operazione devo compierci sopra
//Questa parte serve per gestire l'assoc_array degli status
if ((rec.empty()) && (status != NODO_RIMOSSO))
{ //Chiave non trovata: la chiave ricercata non è presente nella cache
fatal_box("Errore nella lettura della cache o nella costruzione del record.");
}
_status_node.remove(id.string());
return rec; //Ritorno un Trectype e passo la stauts node
}
//Setta lo stato del nodo: cioè decide che cosa dovrò fare con questo nodo //Setta lo stato del nodo: cioè decide che cosa dovrò fare con questo nodo
void TInsert_albero::set_status_node(const TNumeric_id &id, const char *status) void TAlbero_locale::set_status_node(const TNumeric_id &id, const char *status)
{ {
// STATUS A priorità assoluta e rimane sempre A // STATUS A priorità assoluta e rimane sempre A
// STATUS M priorità su R ma non su A // STATUS M priorità su R ma non su A
@ -424,7 +478,7 @@ void TInsert_albero::set_status_node(const TNumeric_id &id, const char *status)
} }
//Restituisce un nuovo id //Restituisce un nuovo id
TNumeric_id &TInsert_albero::new_id(TNumeric_id id) TNumeric_id &TAlbero_locale::new_id(TNumeric_id id)
{ {
if (id == ID_NULLO) if (id == ID_NULLO)
_last_insert_id+1; _last_insert_id+1;
@ -435,12 +489,12 @@ TNumeric_id &TInsert_albero::new_id(TNumeric_id id)
//Inserisce il nodo (che ho in ingresso) nella struttura ad albero doppiamente linkata //Inserisce il nodo (che ho in ingresso) nella struttura ad albero doppiamente linkata
//di relana aggiornando tutti i link //di relana aggiornando tutti i link
bool TInsert_albero::insert_node(TRectype & node,const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id) bool TAlbero_locale::insert_node(TRectype & node,const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id)
{ {
TNumeric_id id_succ; TNumeric_id id_succ;
TToken_string key; TToken_string key;
key.add(node.get(ABRA_CODAN)); key=get_headkey();
TRectype parente(LF_RELANA); TRectype parente(current());
if (id == ID_NULLO) if (id == ID_NULLO)
id = new_id(id); id = new_id(id);
else else
@ -449,9 +503,9 @@ bool TInsert_albero::insert_node(TRectype & node,const TNumeric_id id_prec, cons
if (id_prec != ID_NULLO) if (id_prec != ID_NULLO)
{ //Aggiorno il successivo del mio precedente dicendogli che il suo successivo sono io { //Aggiorno il successivo del mio precedente dicendogli che il suo successivo sono io
key.add(id_prec.string()); key.add(id_prec.string());
parente = _ana_cache->get(key); parente = _local_cahe->get(key);
parente.put(ABRA_IDSUCC,id.string()); parente.put(ABRA_IDSUCC,id.string());
_ana_cache->put(parente); _local_cahe->put(parente);
set_status_node(id_prec,NODO_MODIFICATO); //Setto l'eventuale flag di array modificato per il fratello set_status_node(id_prec,NODO_MODIFICATO); //Setto l'eventuale flag di array modificato per il fratello
} }
else else
@ -459,9 +513,9 @@ bool TInsert_albero::insert_node(TRectype & node,const TNumeric_id id_prec, cons
if (id_padre != ID_NULLO) if (id_padre != ID_NULLO)
{ //Sono un primo figlio: rintraccio mio padre e gli dico che il suo primo figlio ora, sono io { //Sono un primo figlio: rintraccio mio padre e gli dico che il suo primo figlio ora, sono io
key.add(id_padre.string()); key.add(id_padre.string());
parente = _ana_cache->get(key); parente = _local_cahe->get(key);
parente.put(ABRA_IDFIGLIO,id.string()); parente.put(ABRA_IDFIGLIO,id.string());
_ana_cache->put(parente); _local_cahe->put(parente);
set_status_node(id_padre,NODO_MODIFICATO); //Setto l'eventuale flag di array modificato per il padre set_status_node(id_padre,NODO_MODIFICATO); //Setto l'eventuale flag di array modificato per il padre
} // Sono una radice principale e quindi sono orfana di padre } // Sono una radice principale e quindi sono orfana di padre
} }
@ -471,7 +525,7 @@ bool TInsert_albero::insert_node(TRectype & node,const TNumeric_id id_prec, cons
node.put(ABRA_IDPADRE,id_padre.string()); node.put(ABRA_IDPADRE,id_padre.string());
node.put(ABRA_IDSUCC,id_succ.string()); node.put(ABRA_IDSUCC,id_succ.string());
node.put(ABRA_IDFIGLIO,ID_NULLO); node.put(ABRA_IDFIGLIO,ID_NULLO);
_ana_cache->put(node); _local_cahe->put(node);
//set_current(node); //set_current(node);
goto_node(node); goto_node(node);
set_status_node(id,NODO_MODIFICATO); set_status_node(id,NODO_MODIFICATO);
@ -480,14 +534,14 @@ bool TInsert_albero::insert_node(TRectype & node,const TNumeric_id id_prec, cons
//Questa funzione aggiorna i link dei "parenti" di un nodo che sta per essere rimosso //Questa funzione aggiorna i link dei "parenti" di un nodo che sta per essere rimosso
bool TInsert_albero::delete_node(const TNumeric_id &id) bool TAlbero_locale::delete_node(const TNumeric_id &id)
{ {
TRectype parente(LF_RELANA); TRectype parente(current());
TNumeric_id id_padre, id_figlio, id_prec, id_succ; TNumeric_id id_padre, id_figlio, id_prec, id_succ;
goto_node(id); goto_node(id);
TToken_string key = _currnode->get(ABRA_CODAN); TToken_string key = get_headkey();
// id = _currnode->get_real(ABRA_ID); // id = _currnode->get_real(ABRA_ID);
id_padre = _currnode->get_real(ABRA_IDPADRE); id_padre = _currnode->get_real(ABRA_IDPADRE);
@ -499,11 +553,11 @@ bool TInsert_albero::delete_node(const TNumeric_id &id)
if (id_padre != ID_NULLO) if (id_padre != ID_NULLO)
{ {
key.add(id_padre.string(),1); key.add(id_padre.string(),1);
parente=_ana_cache->get(key); //padre parente=_local_cahe->get(key); //padre
if (parente.get(ABRA_IDFIGLIO) == id.string()) if (parente.get(ABRA_IDFIGLIO) == id.string())
{ //Il nodo che sta per essere rimosso è il primo figlio di un padre { //Il nodo che sta per essere rimosso è il primo figlio di un padre
parente.put(ABRA_IDFIGLIO,id_succ.string()); //Aggiorno il padre parente.put(ABRA_IDFIGLIO,id_succ.string()); //Aggiorno il padre
_ana_cache->put(parente); _local_cahe->put(parente);
} }
} }
@ -512,9 +566,9 @@ bool TInsert_albero::delete_node(const TNumeric_id &id)
if (id_prec != ID_NULLO) if (id_prec != ID_NULLO)
{ {
key.add(id_prec.string(),1); key.add(id_prec.string(),1);
parente=_ana_cache->get(key); //fratello sinistro parente=_local_cahe->get(key); //fratello sinistro
parente.put(ABRA_IDSUCC,id_succ.string()); //Assegno al mio fratello sinistro il mio fratello destro parente.put(ABRA_IDSUCC,id_succ.string()); //Assegno al mio fratello sinistro il mio fratello destro
_ana_cache->put(parente); _local_cahe->put(parente);
} }
//Dico a mio fratello successivo chi il suo precedente non sono più io, //Dico a mio fratello successivo chi il suo precedente non sono più io,
@ -522,9 +576,9 @@ bool TInsert_albero::delete_node(const TNumeric_id &id)
if (id_succ != ID_NULLO) if (id_succ != ID_NULLO)
{ {
key.add(id_succ.string(),1); key.add(id_succ.string(),1);
parente=_ana_cache->get(key); //fratello destro parente=_local_cahe->get(key); //fratello destro
parente.put(ABRA_IDPREC,id_prec.string()); //Assegno al mio fratello destro il mio fratello sinistro parente.put(ABRA_IDPREC,id_prec.string()); //Assegno al mio fratello destro il mio fratello sinistro
_ana_cache->put(parente); _local_cahe->put(parente);
} }
//I miei vicini mi hanno già escluso: non sono più raggiungibile //I miei vicini mi hanno già escluso: non sono più raggiungibile
@ -534,7 +588,7 @@ bool TInsert_albero::delete_node(const TNumeric_id &id)
//node.put(ABRA_IDPADRE,ID_NULLO); //node.put(ABRA_IDPADRE,ID_NULLO);
_currnode->put(ABRA_IDPREC,ID_NULLO); _currnode->put(ABRA_IDPREC,ID_NULLO);
_currnode->put(ABRA_IDSUCC,ID_NULLO); _currnode->put(ABRA_IDSUCC,ID_NULLO);
_ana_cache->put(*_currnode); _local_cahe->put(*_currnode);
//Elimino i miei figli //Elimino i miei figli
TNumeric_id nextnode_id; TNumeric_id nextnode_id;
@ -566,23 +620,22 @@ bool TInsert_albero::delete_node(const TNumeric_id &id)
return TRUE; return TRUE;
} }
void TInsert_albero::zero() void TAlbero_locale::zero()
{ {
delete_tree(); // cancella l'albero delete_tree(); // cancella l'albero
_status_node.destroy(); _status_node.destroy();
_currnode->put(ABRA_ID,ID_NULLO); _currnode->put(ABRA_ID,ID_NULLO);
} }
bool TInsert_albero::delete_tree() bool TAlbero_locale::delete_tree()
{ {
goto_root(); goto_root();
remove_subtree(ID_NULLO); //Non eliminando il link coi fratelli della radice, remove_subtree naviga tutto l'albero remove_subtree(ID_NULLO); //Non eliminando il link coi fratelli della radice, remove_subtree naviga tutto l'albero
return TRUE; return TRUE;
} }
//Questa funzione elimina tutti i nodi sottostanti al nodo //Questa funzione elimina il nodo corrente e tutti i nodi sottostanti
//"principale" che sta per essere eliminato bool TAlbero_locale::remove_subtree(const TNumeric_id return_id)
bool TInsert_albero::remove_subtree(const TNumeric_id thisnode_id)
{ {
TNumeric_id myself_id; TNumeric_id myself_id;
//cerco il figlio //cerco il figlio
@ -623,47 +676,47 @@ bool TInsert_albero::remove_subtree(const TNumeric_id thisnode_id)
//non è previsto uno status, non dovrebbe esistere nella cache //non è previsto uno status, non dovrebbe esistere nella cache
CHECK (FALSE,"Errore nella consistenza della cache"); CHECK (FALSE,"Errore nella consistenza della cache");
} }
if (thisnode_id != ID_NULLO) if (return_id != ID_NULLO)
goto_node(thisnode_id); goto_node(return_id);
else else
_currnode->put(ABRA_ID,ID_NULLO); _currnode->put(ABRA_ID,ID_NULLO);
return TRUE; return TRUE;
} }
bool TInsert_albero::has_son() bool TAlbero_locale::has_son()
{ {
return (_currnode->get_real(ABRA_IDFIGLIO) != ID_NULLO); return (_currnode->get_real(ABRA_IDFIGLIO) != ID_NULLO);
} }
bool TInsert_albero::goto_firstson() bool TAlbero_locale::goto_firstson()
{ {
goto_node(_currnode->get_real(ABRA_IDFIGLIO)); goto_node(_currnode->get_real(ABRA_IDFIGLIO));
return TRUE; return TRUE;
} }
bool TInsert_albero::has_rbrother() bool TAlbero_locale::has_rbrother()
{ {
return (_currnode->get_real(ABRA_IDSUCC) != ID_NULLO); return (_currnode->get_real(ABRA_IDSUCC) != ID_NULLO);
} }
bool TInsert_albero::goto_rbrother() bool TAlbero_locale::goto_rbrother()
{ {
goto_node(_currnode->get_real(ABRA_IDSUCC)); goto_node(_currnode->get_real(ABRA_IDSUCC));
return TRUE; return TRUE;
} }
bool TInsert_albero::goto_root() bool TAlbero_locale::goto_root()
{ //Il _current sarà posizionato sull'ultimo nodo che è stato visitato { //Il _current sarà posizionato sull'ultimo nodo che è stato visitato
if (current()->get_real(ABRA_ID)==ID_NULLO) if (current().get_real(id_fieldname())==ID_NULLO)
return FALSE; return FALSE;
TToken_string key; TToken_string key;
TNumeric_id id_prec, id_padre; TNumeric_id id_prec, id_padre;
key.add(_currnode->get(ABRA_CODAN)); key=get_headkey();
key.add(_currnode->get(ABRA_ID)); key.add(_currnode->get(ABRA_ID));
do do
{ {
*_currnode = _ana_cache->get(key); *_currnode = _local_cahe->get(key);
id_prec = _currnode->get_real(ABRA_IDPREC); id_prec = _currnode->get_real(ABRA_IDPREC);
id_padre = _currnode->get_real(ABRA_IDPADRE); id_padre = _currnode->get_real(ABRA_IDPADRE);
if (id_prec != ID_NULLO) if (id_prec != ID_NULLO)
@ -679,6 +732,15 @@ bool TInsert_albero::goto_root()
return TRUE; return TRUE;
} }
void TAlbero_locale::goto_node(const TNumeric_id id)
{
TToken_string key;
key=get_headkey();
key.add(id.string());
*_currnode = _local_cahe->get(key);
}
/**************************************************************************************************/ /**************************************************************************************************/
// TAlbero_relana // TAlbero_relana
/**************************************************************************************************/ /**************************************************************************************************/

View File

@ -29,6 +29,9 @@
#include "relana.h" #include "relana.h"
#endif //_RELANA_H #endif //_RELANA_H
#include "saldi.h"
#include "movdett.h"
#define TIPO_ANALISI "A" #define TIPO_ANALISI "A"
@ -207,11 +210,10 @@ public:
// @cmember Distruttore // @cmember Distruttore
virtual ~TAlbero_relvoci() ; virtual ~TAlbero_relvoci() ;
}; };
// Struttura da albero basata su un file temporaneo cached // Struttura da albero basata su un file temporaneo cached
class TInsert_albero : public TAlbero_bidir class TAlbero_locale : public TAlbero_bidir
{ {
TRWrecord_cache * _ana_cache; TRWrecord_cache * _local_cahe;
TLocalisamfile *_f; // da rimuovere !! TLocalisamfile *_f; // da rimuovere !!
@ -219,24 +221,25 @@ class TInsert_albero : public TAlbero_bidir
TNumeric_id _last_insert_id; TNumeric_id _last_insert_id;
TAssoc_array _status_node; TAssoc_array _status_node;
// debug
void write_cache() { _ana_cache->flush(); }
protected: protected:
// debug
void write_cache() { _local_cahe->flush(); }
// @cmember Elimina il sottoalbero dei figli di un nodo // @cmember Elimina il sottoalbero dei figli di un nodo
// @cmember che sta per essere eliminato da un struttura di tipo lista doppiamente lincata // @cmember che sta per essere eliminato da un struttura di tipo lista doppiamente lincata
bool remove_subtree(const TNumeric_id lastnode_id); bool remove_subtree(const TNumeric_id lastnode_id);
// @cmember genera/setta il nuovo id // @cmember genera/setta il nuovo id
TNumeric_id &new_id(TNumeric_id); TNumeric_id &new_id(TNumeric_id);
void goto_node(const TNumeric_id id) void goto_node(const TNumeric_id id);
{
TToken_string key;
key.add(_currnode->get(ABRA_CODAN));
key.add(id.string());
*_currnode = _ana_cache->get(key);
}
void goto_node(TRectype &node) {*_currnode = node;} void goto_node(TRectype &node) {*_currnode = node;}
virtual const char * idfather_fieldname() pure ;
virtual const char * idson_fieldname() pure;
virtual const char * idsucc_fieldname() pure;
virtual const char * idprec_fieldname() pure;
virtual const char * id_fieldname() pure;
virtual const char * get_headkey();
public: public:
// @cmember Inserisce un nodo in una struttura di tipo lista doppiamente lincata // @cmember Inserisce un nodo in una struttura di tipo lista doppiamente lincata
bool insert_node(TRectype &node, const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id); bool insert_node(TRectype &node, const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id);
@ -247,7 +250,7 @@ protected:
// @cmember Lancia la rimozione di tutto l'albero // @cmember Lancia la rimozione di tutto l'albero
void zero(); void zero();
// @cmember Restituisce il nodo corrente // @cmember Restituisce il nodo corrente
TRectype * current() const {return (TRectype * )_currnode;} TRectype & current() const {return *_currnode;}
// @cmember Restituisce TRUE se esiste un figlio di un nodo // @cmember Restituisce TRUE se esiste un figlio di un nodo
virtual bool has_son(); virtual bool has_son();
@ -264,21 +267,95 @@ protected:
// ***** gestione interfaccia Database/copia locale // ***** gestione interfaccia Database/copia locale
// @cmember Estrae un nodo dall'albero // @cmember Estrae un nodo dall'albero
TRectype extract_node(const TString &codtab,TNumeric_id &id, TString& status); TRectype extract_dirtynode(TNumeric_id &id, TString& status);
// @cmember Ritorna il numero di elementi dell'assoc_array status_node // @cmember Ritorna il numero di elementi dell'assoc_array status_node
int status_node_items() { return _status_node.items();} int dirty_nodes() { return _status_node.items();}
// @cmember Setta lo stato del nodo: valori ammessi = nodo <A>ggiunto, nodo <M>odificato, nodo <R>imosso // @cmember Setta lo stato del nodo: valori ammessi = nodo <A>ggiunto, nodo <M>odificato, nodo <R>imosso
void set_status_node(const TNumeric_id &id, const char *status); void set_status_node(const TNumeric_id &id, const char *status);
// @cmember Ritorna lo stato di un nodo // @cmember Ritorna lo stato di un nodo
const char* get_status_node(const TNumeric_id &id); const char* get_status_node(const TNumeric_id &id);
public:
// @cmember Costruttore // @cmember Costruttore
TInsert_albero(); TAlbero_locale(int filenum);
// @cmember Distruttore // @cmember Distruttore
virtual ~TInsert_albero(); virtual ~TAlbero_locale();
}; };
class TAnalisi_bil: public TRectype // Copia locale dell'albero di una tabella analisi
class TLocal_relana3 : public TAlbero_locale
{
protected:
virtual const char * idfather_fieldname() {return ABRA_IDPADRE;}
virtual const char * idson_fieldname(){return ABRA_IDFIGLIO;}
virtual const char * idsucc_fieldname(){return ABRA_IDSUCC;}
virtual const char * idprec_fieldname(){return ABRA_IDPREC;}
virtual const char * id_fieldname(){return ABRA_IDPADRE;}
virtual const char * get_headkey() {return " ";}
public:
// @cmember Costruttore
TLocal_relana3();
// @cmember Distruttore
virtual ~TLocal_relana3();
};
// Copia locale dell'albero dei dettagli di un saldo
class TLocal_balance3 : public TAlbero_locale
{
protected:
virtual const char * idfather_fieldname() {return ABMD_IDPADRE;}
virtual const char * idson_fieldname(){return ABMD_IDFIGLIO;}
virtual const char * idsucc_fieldname(){return ABMD_IDSUCC;}
virtual const char * idprec_fieldname(){return ABMD_IDPREC;}
virtual const char * id_fieldname(){return ABMD_IDPADRE;}
virtual const char * get_headkey() {return " | | | ";}
public:
// @cmember Costruttore
TLocal_balance3();
// @cmember Distruttore
virtual ~TLocal_balance3();
};
class TAlbero_AB: public TRectype
{
protected:
TAlbero_locale *_inter_tree;
// @cmember Esegue la scrittura del body del record
virtual int commit_body() const;
// @cmember Esegue la lettura del body del rocord
virtual int read_body(bool lockstruct);
// @cmember Copia la chiave sul record dei nodi dell'albero
virtual void put_headkey(TRectype &rec) const;
public:
// @cmember Costruttore
TAlbero_AB(int filenum);
// #cmember Distruttore
virtual ~TAlbero_AB() ;
// @cmember Esegue la lettura della testata di un record da LF_ANALISI e del suo "body"
virtual int read(TBaseisamfile& analisi, word isop=_isequal, word lockop=_nolock);
// @cmember Esegue la lettura della testata di un record alla posizione nrec da LF_ANALISI e del suo "body"
virtual int readat(TBaseisamfile& f, TRecnotype nrec, word lockop = _nolock);
// @cmember Scrive una tabella di analisi
virtual int write(TBaseisamfile& analisi) const;
// @cmember Riscrive una tabella di analisi
virtual int rewrite(TBaseisamfile& analisi) const;
// @cmember Elimina una intera tabella di analisi con tutto il suo contenuto
virtual int remove(TBaseisamfile& f) const;
// @cmember Azzera l record
virtual void zero();
TAlbero_locale * user_tree()
{return _inter_tree;}
};
class TAnalisi_bil: public TAlbero_AB
{ {
class TArray_fratelli: public TAssoc_array class TArray_fratelli: public TAssoc_array
{ {
@ -293,7 +370,7 @@ class TAnalisi_bil: public TRectype
TLocalisamfile *_voci; TLocalisamfile *_voci;
TAlbero_relvoci *_relaz; TAlbero_relvoci *_relaz;
TAlbero_relana *_ana; TAlbero_relana *_ana;
TInsert_albero *_inter_tree; TLocal_relana3 *_inter_tree;
TRectype * _newrec; //buffer per l'inserimento dodo per nodo TRectype * _newrec; //buffer per l'inserimento dodo per nodo
protected: protected:
// @cmember Esegue una navigazione dell'albero di rel_voci e di rel_ana // @cmember Esegue una navigazione dell'albero di rel_voci e di rel_ana
@ -309,32 +386,42 @@ class TAnalisi_bil: public TRectype
bool lock_tabella(); bool lock_tabella();
// @cmember Sblocca una tabella di analisi // @cmember Sblocca una tabella di analisi
bool unlock_tabella(); bool unlock_tabella();
// @cmember Esegue la scrittura del body del record scrive il contenuto di una tabella di analisi
virtual int commit_body() const;
// @cmember Esegue la lettura del body del rocord: legge il contenuto di una tabella di analisi
virtual int read_body(bool lockstruct);
// @cmember Copia la chiave sul record dei nodi dell'albero
virtual void put_headkey(TRectype &rec) const;
public: public:
// @cmember Costruttore // @cmember Costruttore
TAnalisi_bil(); TAnalisi_bil();
// #cmember Distruttore // #cmember Distruttore
virtual ~TAnalisi_bil() ; virtual ~TAnalisi_bil() ;
// @cmember Ritrona il tipo di analisi // @cmember Ritorna il tipo di analisi
const TString &type() {return get(ABAN_TIPOAN);} const TString &type() {return get(ABAN_TIPOAN);}
// @cmember Setta il tipo di analisi // @cmember Setta il tipo di analisi
void set_type(const char * tipo) {put(ABAN_TIPOAN,tipo);} void set_type(const char * tipo) {put(ABAN_TIPOAN,tipo);}
// @cmember Esegue la lettura della testata di un record da LF_ANALISI
virtual int read(TBaseisamfile& analisi, word isop=_isequal, word lockop=_nolock);
// @cmember Esegue la lettura della testata di un record alla posizione nrec da LF_ANALISI
virtual int readat(TBaseisamfile& f, TRecnotype nrec, word lockop = _nolock);
// @cmember Serve per lanciare la scrittura del body del record
virtual int write(TBaseisamfile& analisi) const;
// @cmember Elimina una intera tabella di analisi con tutto il suo contenuto
virtual int remove(TBaseisamfile& f) const;
// @cmember Azzera l record
virtual void zero();
// @cmember Esegue la scrittura del body del record scrive il contenuto di una tabella di analisi
int commit_body(TLocalisamfile &relana) const;
// @cmember Esegue la lettura del body del rocord: legge il contenuto di una tabella di analisi
int read_body(bool lockstruct);
// @cmember Restituisce l'oggetto ad albero "copia locale"
TInsert_albero & user_tree()
{return *_inter_tree;}
}; };
class TABsaldo: public TRectype
{
TLocalisamfile *_saldi;
TAlbero_relana *_movdett;
TLocal_balance3 *_inter_tree;
TRectype * _newrec; //buffer per l'inserimento dodo per nodo
protected:
// @cmember Esegue la scrittura del body del record scrive il contenuto di una tabella di analisi
virtual int commit_body() const;
// @cmember Esegue la lettura del body del rocord: legge il contenuto di una tabella di analisi
virtual int read_body(bool lockstruct);
// @cmember Copia la chiave sul record dei nodi dell'albero
virtual void put_headkey(TRectype &rec) const;
public:
// @cmember Costruttore
TABsaldo();
// #cmember Distruttore
virtual ~ TABsaldo() ;
};
#endif //__ANALISI_H #endif //__ANALISI_H