From f1c8e53279adc4898254c4b7058028b0d500a996 Mon Sep 17 00:00:00 2001 From: sauro Date: Tue, 20 Jan 1998 10:14:04 +0000 Subject: [PATCH] =?UTF-8?q?Modificata=20la=20gestione=20degli=20"status"?= =?UTF-8?q?=20dei=20nodi:=20prima=20metteva=20sempre=20nodo=20modificato?= =?UTF-8?q?=20anche=20quando=20in=20realt=C3=A0=20non=20modificava=20nulla?= =?UTF-8?q?.=20Modificata=20di=20conseguenza=20anche=20la=20funzione=20per?= =?UTF-8?q?=20la=20rimozione=20dei=20nodi=20che=20si=20basava=20sugli=20"s?= =?UTF-8?q?tatus".?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: svn://10.65.10.50/trunk@5979 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- ab/ab3100.cpp | 4 +- ab/ablib01.cpp | 152 +++++++++++++++---------------------------------- ab/ablib01.h | 11 +++- 3 files changed, 58 insertions(+), 109 deletions(-) diff --git a/ab/ab3100.cpp b/ab/ab3100.cpp index 5027c444f..9c2ab9232 100755 --- a/ab/ab3100.cpp +++ b/ab/ab3100.cpp @@ -12,8 +12,8 @@ void test_analisi() anas.put(ABAN_CODAN,"A1"); anas.read(); // readat -> vedi dopo - anas.remove(); //Solo per il test della delete_node o la rimozione di una intera tabella - //anas.write(); + //anas.remove(); //Solo per il test della delete_node o la rimozione di una intera tabella + anas.write(); /*Questa parte della funzione serve solo per testare la readat diff --git a/ab/ablib01.cpp b/ab/ablib01.cpp index f5c00e64a..abae7f0cb 100755 --- a/ab/ablib01.cpp +++ b/ab/ablib01.cpp @@ -1,10 +1,4 @@ #include "ablib01.h" - -#define MAX_ID_REL 999999999 -#define NODO_AGGIUNTO "A" -#define NODO_MODIFICATO "M" -#define NODO_RIMOSSO "R" - /**************************************************************************************************/ // TAlbero_AB /**************************************************************************************************/ @@ -63,11 +57,11 @@ int TAlbero_AB::readat(TBaseisamfile& analisi, TRecnotype nrec, word lockop) 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 // TLocalisamfile lf(LF_RELANA); TNumeric_id id; - id = 17; + id = 4; _inter_tree->delete_node(id); int errc = commit_body(); if (errc != NOERR) @@ -76,10 +70,10 @@ int TAlbero_AB::remove(TBaseisamfile& f) const //return errc; } 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(); int errc = commit_body(); if (errc != NOERR) @@ -88,7 +82,7 @@ int TAlbero_AB::remove(TBaseisamfile& f) const //return errc; } int err = TRectype::remove(f); - return err; */ + return err; } void TAlbero_AB::zero() @@ -129,65 +123,9 @@ void TABsaldo::put_headkey(TRectype &rec) const 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 int TABsaldo::read_body(bool lockstruct) { - //_ana = new TAlbero_relana(get(ABAN_CODAN)); TString codditta = get(ABS_CODDITTA); TToken_string key = codditta.right_just(5,'0'); key.add(get(ABS_ANNO)); @@ -198,11 +136,9 @@ int TABsaldo::read_body(bool lockstruct) if (_mov->goto_root()) { - //TNumeric_id id_movdett; - //id_movdett = _mov->curr().get_real(ABMD_ID); naviga_movdett(); } - //_inter_tree->write_cache(); //solo per debug +// _inter_tree->write_cache(); //solo per debug return 0; } @@ -217,7 +153,7 @@ void TABsaldo::naviga_movdett() pather_id = _mov->curr().get_real(ABMD_IDPADRE); lbrother_id = _mov->curr().get_real(ABMD_IDPREC); *_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()) { @@ -282,7 +218,7 @@ int TAlbero_AB::commit_body() const while (_inter_tree->dirty_nodes() > 0) { TNumeric_id id; -// int prova = _inter_tree->dirty_nodes(); solo debug +// int prova = _inter_tree->dirty_nodes(); //solo debug id=ID_NULLO; 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); _newrec = sincronizza_relana(begin_relana, id_relana); 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 if (_relaz->has_rbrother()) @@ -377,7 +313,6 @@ void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNum //fra relvoci e relana TNumeric_id frat_relana; 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); } 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); } 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 _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 //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; TToken_string key; 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 key.add(id_prec.string()); parente = _local_cache->get(key); - 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 + if (parente.get_real(idsucc_fieldname()) != id) + {// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status + 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 { //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 key.add(id_padre.string()); parente = _local_cache->get(key); - 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 + if(parente.get_real(idson_fieldname()) != id) + {// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status + 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 } //Ora aggiorno me stesso put_headkey(node); -// node.put(ABRA_CODAN,get_headkey()); //Eseguo un combio della chiave: non serve avere il codice della tabella nella cache - node.put(idprec_fieldname(),id_prec.string()); - node.put(idfather_fieldname(),id_padre.string()); - node.put(idsucc_fieldname(),id_succ.string()); - node.put(idson_fieldname(),ID_NULLO); + if ((node.get_real(idprec_fieldname()) != id_prec) || + (node.get_real(idfather_fieldname()) != id_padre)) + {// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status + node.put(idprec_fieldname(),id_prec.string()); + 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); - //set_current(node); goto_node(node); - set_status_node(id,dirty_value); return TRUE; } @@ -721,7 +668,8 @@ bool TAlbero_locale::delete_node(const TNumeric_id &id) parente=_local_cache->get(key); //padre if (parente.get(idson_fieldname()) == id.string()) { //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); } } @@ -735,6 +683,7 @@ bool TAlbero_locale::delete_node(const TNumeric_id &id) key.add(id_prec.string()); parente=_local_cache->get(key); //fratello sinistro 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); } @@ -747,6 +696,7 @@ bool TAlbero_locale::delete_node(const TNumeric_id &id) key.add(id_succ.string()); parente=_local_cache->get(key); //fratello destro 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); } @@ -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 TString *status; status = (TString*)_status_node.objptr(id.string()); - if (status != ID_NULLO) - {//Se esiste uno stato per questo nodo - if ((*status == NODO_MODIFICATO) || (*status == NODO_RIMOSSO)) - {//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()); - } + if ((status == NULL) || (*status != NODO_AGGIUNTO)) + {//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 - { - //Questo caso non dovrebbe verificarsi poichè un nodo per cui - //non è previsto uno status, non dovrebbe esistere nella cache - CHECK (FALSE,"Errore nella consistenza della cache"); + {//Nel caso di NODO_AGGIUNTO + _status_node.remove(id.string()); } + if (return_id != ID_NULLO) goto_node(return_id); else diff --git a/ab/ablib01.h b/ab/ablib01.h index ae80ff12e..dd10393da 100755 --- a/ab/ablib01.h +++ b/ab/ablib01.h @@ -31,6 +31,13 @@ #include "saldi.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 void write_cache() { _local_cache->flush(); } - // @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); + // @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, const char trasf_immes); // @cmember Elimina un nodo da una struttura di tipo lista doppiamente lincata bool delete_node(const TNumeric_id &id); // @cmember Lancia la rimozione di tutto l'albero