Modificata la gestione degli "status" dei nodi: prima metteva sempre nodo modificato

anche quando in realtà non modificava nulla.
Modificata di conseguenza anche la funzione per la rimozione dei nodi che si basava
sugli "status".


git-svn-id: svn://10.65.10.50/trunk@5979 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
sauro 1998-01-20 10:14:04 +00:00
parent c497f91f9f
commit f1c8e53279
3 changed files with 58 additions and 109 deletions

View File

@ -12,8 +12,8 @@ void test_analisi()
anas.put(ABAN_CODAN,"A1"); anas.put(ABAN_CODAN,"A1");
anas.read(); anas.read();
// readat -> vedi dopo // readat -> vedi dopo
anas.remove(); //Solo per il test della delete_node o la rimozione di una intera tabella //anas.remove(); //Solo per il test della delete_node o la rimozione di una intera tabella
//anas.write(); anas.write();
/*Questa parte della funzione serve solo per testare la readat /*Questa parte della funzione serve solo per testare la readat

View File

@ -1,10 +1,4 @@
#include "ablib01.h" #include "ablib01.h"
#define MAX_ID_REL 999999999
#define NODO_AGGIUNTO "A"
#define NODO_MODIFICATO "M"
#define NODO_RIMOSSO "R"
/**************************************************************************************************/ /**************************************************************************************************/
// TAlbero_AB // TAlbero_AB
/**************************************************************************************************/ /**************************************************************************************************/
@ -63,11 +57,11 @@ int TAlbero_AB::readat(TBaseisamfile& analisi, TRecnotype nrec, word lockop)
int TAlbero_AB::remove(TBaseisamfile& f) const int TAlbero_AB::remove(TBaseisamfile& f) const
{ {
//*Abilitare questa parte solo per effettuare un debug della delete_node /*Abilitare questa parte solo per effettuare un debug della delete_node
// anche se messa in questa posizione, la chiamata non ha senso // anche se messa in questa posizione, la chiamata non ha senso
// TLocalisamfile lf(LF_RELANA); // TLocalisamfile lf(LF_RELANA);
TNumeric_id id; TNumeric_id id;
id = 17; id = 4;
_inter_tree->delete_node(id); _inter_tree->delete_node(id);
int errc = commit_body(); int errc = commit_body();
if (errc != NOERR) if (errc != NOERR)
@ -76,10 +70,10 @@ int TAlbero_AB::remove(TBaseisamfile& f) const
//return errc; //return errc;
} }
return 0; return 0;
*/
/*Abilitare solo questa parte per il test della remove_tree //*Abilitare solo questa parte per il test della remove_tree
_inter_tree->delete_tree(); _inter_tree->delete_tree();
int errc = commit_body(); int errc = commit_body();
if (errc != NOERR) if (errc != NOERR)
@ -88,7 +82,7 @@ int TAlbero_AB::remove(TBaseisamfile& f) const
//return errc; //return errc;
} }
int err = TRectype::remove(f); int err = TRectype::remove(f);
return err; */ return err;
} }
void TAlbero_AB::zero() void TAlbero_AB::zero()
@ -129,65 +123,9 @@ void TABsaldo::put_headkey(TRectype &rec) const
rec.put(ABMD_CODCBL, get(ABS_CODCBL)); rec.put(ABMD_CODCBL, get(ABS_CODCBL));
} }
/*
int TABsaldo::commit_body() const
{
_inter_tree->write_cache();
TRectype rec(_inter_tree->current().num());
TLocalisamfile filebody(rec.num());
TString status;
//Estraggo un nodo per volta basandomi sull'assoc_array degli status
while (_inter_tree->dirty_nodes() > 0)
{
TNumeric_id id;
//int prova = _inter_tree->dirty_nodes(); //solo debug
id=ID_NULLO;
rec= _inter_tree->extract_dirtynode(id, status);
put_headkey(rec);
//Ho un rectype e uno status node
if (status == NODO_AGGIUNTO)
{
if (filebody.curr().empty())
{ //Se il cursor di relana è posizionato in modo errato:
//lo sistemo sull'ultimo record del file
//DOMANDA: - Perchè ???
//TENATATIVO DI RISPOSTA: - Quando l'ultima azione effettuata (prima di questa "aggiunta") è la rimozione
// dell'ultimo record probabilmente (ma non sono sicuro) il cursore non è posizionato (o forse
// è posizionato in modo errato come ad es. dopo l'EOF, visto che l'EOF era sull'ultimo record rimosso)
// e quando eseguo un tentativo di scrittura da un errore di chiave duplicata (anche se questa non esiste);
// 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.
//RISPOSTA ESATTA: - Bho !!!
filebody.last();
}
int err = filebody.write(rec);
if (err != NOERR)
return err;
}
if (status == NODO_MODIFICATO)
{
int err = filebody.rewrite(rec);
if (err != NOERR)
return err;
}
if (status == NODO_RIMOSSO)
{
filebody.read(rec); //Devo leggere sul file per posizionare il cursore: stesso motivo di prima
int err = filebody.remove(rec);
if (err != NOERR)
return err;
}
// In tutti gli altri casi il nodo non viene modificato
}
return NOERR;
}
*/
//Leggo il "corpo" del record //Leggo il "corpo" del record
int TABsaldo::read_body(bool lockstruct) int TABsaldo::read_body(bool lockstruct)
{ {
//_ana = new TAlbero_relana(get(ABAN_CODAN));
TString codditta = get(ABS_CODDITTA); TString codditta = get(ABS_CODDITTA);
TToken_string key = codditta.right_just(5,'0'); TToken_string key = codditta.right_just(5,'0');
key.add(get(ABS_ANNO)); key.add(get(ABS_ANNO));
@ -198,11 +136,9 @@ int TABsaldo::read_body(bool lockstruct)
if (_mov->goto_root()) if (_mov->goto_root())
{ {
//TNumeric_id id_movdett;
//id_movdett = _mov->curr().get_real(ABMD_ID);
naviga_movdett(); naviga_movdett();
} }
//_inter_tree->write_cache(); //solo per debug // _inter_tree->write_cache(); //solo per debug
return 0; return 0;
} }
@ -217,7 +153,7 @@ void TABsaldo::naviga_movdett()
pather_id = _mov->curr().get_real(ABMD_IDPADRE); pather_id = _mov->curr().get_real(ABMD_IDPADRE);
lbrother_id = _mov->curr().get_real(ABMD_IDPREC); lbrother_id = _mov->curr().get_real(ABMD_IDPREC);
*_newrec = _mov->curr(); *_newrec = _mov->curr();
_inter_tree->insert_node(*_newrec,lbrother_id,pather_id,my_id); _inter_tree->insert_node(*_newrec,lbrother_id,pather_id,my_id,TRASFERITO);
if (_mov->has_rbrother()) if (_mov->has_rbrother())
{ {
@ -282,7 +218,7 @@ int TAlbero_AB::commit_body() const
while (_inter_tree->dirty_nodes() > 0) while (_inter_tree->dirty_nodes() > 0)
{ {
TNumeric_id id; TNumeric_id id;
// int prova = _inter_tree->dirty_nodes(); solo debug // int prova = _inter_tree->dirty_nodes(); //solo debug
id=ID_NULLO; id=ID_NULLO;
rec= _inter_tree->extract_dirtynode(id, status); rec= _inter_tree->extract_dirtynode(id, status);
@ -366,7 +302,7 @@ void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNum
_relaz->curr_id(key_rel); _relaz->curr_id(key_rel);
_newrec = sincronizza_relana(begin_relana, id_relana); _newrec = sincronizza_relana(begin_relana, id_relana);
currid=_newrec->get_real(ABRA_ID); currid=_newrec->get_real(ABRA_ID);
_inter_tree->insert_node(*_newrec,id_prec,id_padre,currid); _inter_tree->insert_node(*_newrec,id_prec,id_padre,currid,TRASFERITO);
//Controllo se c'è un fratello di rel_voci //Controllo se c'è un fratello di rel_voci
if (_relaz->has_rbrother()) if (_relaz->has_rbrother())
@ -377,7 +313,6 @@ void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNum
//fra relvoci e relana //fra relvoci e relana
TNumeric_id frat_relana; TNumeric_id frat_relana;
naviga_relazioni(frat_relana,currid , id_padre); naviga_relazioni(frat_relana,currid , id_padre);
//_ana->goto_node(key_ana); //Per risalire al nodo che mi ha chiamato in relana
_relaz->goto_node(key_rel); _relaz->goto_node(key_rel);
} }
else else
@ -396,7 +331,6 @@ void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNum
id_relana=_ana->curr().get_real(ABRA_ID); id_relana=_ana->curr().get_real(ABRA_ID);
} }
naviga_relazioni(id_relana, ID_NULLO , currid); naviga_relazioni(id_relana, ID_NULLO , currid);
//_ana->goto_node(key_ana); //Per risalire al nodo che mi ha chiamato in relana
}//Se non trovo il figlio di una relazione, potrebbe essere una foglia di un ramo dell'albero }//Se non trovo il figlio di una relazione, potrebbe essere una foglia di un ramo dell'albero
_relaz->goto_node(key_rel); //Per risalire al nodo che mi ha chiamato in relvoci _relaz->goto_node(key_rel); //Per risalire al nodo che mi ha chiamato in relvoci
} }
@ -649,9 +583,9 @@ TNumeric_id &TAlbero_locale::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 TAlbero_locale::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, const char flag_it)
{ {
const int dirty_value=NODO_MODIFICATO; const char* dirty_value=NODO_MODIFICATO;
TNumeric_id id_succ; TNumeric_id id_succ;
TToken_string key; TToken_string key;
key=get_headkey(); key=get_headkey();
@ -665,9 +599,12 @@ bool TAlbero_locale::insert_node(TRectype & node,const TNumeric_id id_prec, cons
{ //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 = _local_cache->get(key); parente = _local_cache->get(key);
parente.put(idsucc_fieldname(),id.string()); if (parente.get_real(idsucc_fieldname()) != id)
_local_cache->put(parente); {// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status
set_status_node(id_prec,dirty_value); //Setto l'eventuale flag di array modificato per il fratello parente.put(idsucc_fieldname(),id.string());
_local_cache->put(parente);
set_status_node(id_prec,dirty_value); //Setto l'eventuale flag di array modificato per il fratello
}
} }
else else
{ //Se non ho il mio precedente, allora o sono una radice principale o divento il primo figlio: { //Se non ho il mio precedente, allora o sono una radice principale o divento il primo figlio:
@ -675,23 +612,33 @@ bool TAlbero_locale::insert_node(TRectype & node,const TNumeric_id id_prec, cons
{ //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 = _local_cache->get(key); parente = _local_cache->get(key);
parente.put(idson_fieldname(),id.string()); if(parente.get_real(idson_fieldname()) != id)
_local_cache->put(parente); {// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status
set_status_node(id_padre,dirty_value); //Setto l'eventuale flag di array modificato per il padre parente.put(idson_fieldname(),id.string());
_local_cache->put(parente);
set_status_node(id_padre,dirty_value); //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
} }
//Ora aggiorno me stesso //Ora aggiorno me stesso
put_headkey(node); put_headkey(node);
// node.put(ABRA_CODAN,get_headkey()); //Eseguo un combio della chiave: non serve avere il codice della tabella nella cache if ((node.get_real(idprec_fieldname()) != id_prec) ||
node.put(idprec_fieldname(),id_prec.string()); (node.get_real(idfather_fieldname()) != id_padre))
node.put(idfather_fieldname(),id_padre.string()); {// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status
node.put(idsucc_fieldname(),id_succ.string()); node.put(idprec_fieldname(),id_prec.string());
node.put(idson_fieldname(),ID_NULLO); node.put(idfather_fieldname(),id_padre.string());
set_status_node(id,dirty_value);
}
if (flag_it == IMMESSO)
{
node.put(idsucc_fieldname(),id_succ.string());
node.put(idson_fieldname(),ID_NULLO);
//set_current(node);
}
_local_cache->put(node); _local_cache->put(node);
//set_current(node);
goto_node(node); goto_node(node);
set_status_node(id,dirty_value);
return TRUE; return TRUE;
} }
@ -721,7 +668,8 @@ bool TAlbero_locale::delete_node(const TNumeric_id &id)
parente=_local_cache->get(key); //padre parente=_local_cache->get(key); //padre
if (parente.get(idson_fieldname()) == id.string()) if (parente.get(idson_fieldname()) == 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(idson_fieldname(),id_succ.string()); //Aggiorno il padre parente.put(idson_fieldname(),id_succ.string()); //Aggiorno il padre
set_status_node(id_padre, NODO_MODIFICATO); //Aggiorno lo status
_local_cache->put(parente); _local_cache->put(parente);
} }
} }
@ -735,6 +683,7 @@ bool TAlbero_locale::delete_node(const TNumeric_id &id)
key.add(id_prec.string()); key.add(id_prec.string());
parente=_local_cache->get(key); //fratello sinistro parente=_local_cache->get(key); //fratello sinistro
parente.put(idsucc_fieldname(),id_succ.string()); //Assegno al mio fratello sinistro il mio fratello destro parente.put(idsucc_fieldname(),id_succ.string()); //Assegno al mio fratello sinistro il mio fratello destro
set_status_node(id_prec,NODO_MODIFICATO); //Aggiorno lo status
_local_cache->put(parente); _local_cache->put(parente);
} }
@ -747,6 +696,7 @@ bool TAlbero_locale::delete_node(const TNumeric_id &id)
key.add(id_succ.string()); key.add(id_succ.string());
parente=_local_cache->get(key); //fratello destro parente=_local_cache->get(key); //fratello destro
parente.put(idprec_fieldname(),id_prec.string()); //Assegno al mio fratello destro il mio fratello sinistro parente.put(idprec_fieldname(),id_prec.string()); //Assegno al mio fratello destro il mio fratello sinistro
set_status_node(id_succ,NODO_MODIFICATO); //Aggiorno lo status
_local_cache->put(parente); _local_cache->put(parente);
} }
@ -831,23 +781,15 @@ bool TAlbero_locale::remove_subtree(const TNumeric_id return_id)
//in modo tale da mantenerlo allineato con il contenuto della cache //in modo tale da mantenerlo allineato con il contenuto della cache
TString *status; TString *status;
status = (TString*)_status_node.objptr(id.string()); status = (TString*)_status_node.objptr(id.string());
if (status != ID_NULLO) if ((status == NULL) || (*status != NODO_AGGIUNTO))
{//Se esiste uno stato per questo nodo {//In questi due casi il nodo esisteva già nel file originario
if ((*status == NODO_MODIFICATO) || (*status == NODO_RIMOSSO)) _status_node.add(id.string(),(TString)NODO_RIMOSSO,TRUE); //Forzo la sovrascrittura in ogni caso
{//In questi due casi il nodo esisteva già nel file originario
_status_node.add(id.string(),(TString)NODO_RIMOSSO,TRUE); //Forzo la sovrascrittura in ogni caso
}
else
{//Nel caso di NODO_AGGIUNTO
_status_node.remove(id.string());
}
} }
else else
{ {//Nel caso di NODO_AGGIUNTO
//Questo caso non dovrebbe verificarsi poichè un nodo per cui _status_node.remove(id.string());
//non è previsto uno status, non dovrebbe esistere nella cache
CHECK (FALSE,"Errore nella consistenza della cache");
} }
if (return_id != ID_NULLO) if (return_id != ID_NULLO)
goto_node(return_id); goto_node(return_id);
else else

View File

@ -31,6 +31,13 @@
#include "saldi.h" #include "saldi.h"
#include "movdett.h" #include "movdett.h"
#define MAX_ID_REL 999999999
#define NODO_AGGIUNTO "A"
#define NODO_MODIFICATO "M"
#define NODO_RIMOSSO "R"
#define IMMESSO 'I'
#define TRASFERITO 'T'
@ -294,8 +301,8 @@ class TAlbero_locale : public TAlbero_bidir
// debug // debug
void write_cache() { _local_cache->flush(); } void write_cache() { _local_cache->flush(); }
// @cmember Inserisce un nodo in una struttura di tipo lista doppiamente lincata // @cmember Inserisce un nodo in una struttura di tipo lista doppiamente lincata: trasf_immes è un flag che dice se il nodo è trasferito o immesso
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, const char trasf_immes);
// @cmember Elimina un nodo da una struttura di tipo lista doppiamente lincata // @cmember Elimina un nodo da una struttura di tipo lista doppiamente lincata
bool delete_node(const TNumeric_id &id); bool delete_node(const TNumeric_id &id);
// @cmember Lancia la rimozione di tutto l'albero // @cmember Lancia la rimozione di tutto l'albero