Questi file contengono gli strumenti e gli oggetti per l'utilizzo e

la gestione delle strutture ad albero


git-svn-id: svn://10.65.10.50/trunk@5933 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
sauro 1998-01-14 15:03:20 +00:00
parent 958f81b3e4
commit eb541488d1
7 changed files with 1571 additions and 0 deletions

10
ab/ab3.cpp Executable file
View File

@ -0,0 +1,10 @@
#include <xvt.h>
#include <checks.h>
#include "ab3.h"
int main(int argc,char **argv)
{
ab3100(argc,argv);
return 0;
}

6
ab/ab3.h Executable file
View File

@ -0,0 +1,6 @@
#ifndef __AB3_H
#define __AB3_H
void ab3100(int argc, char **argv);
#endif //__AB3_H

38
ab/ab3100.cpp Executable file
View File

@ -0,0 +1,38 @@
#include "ab3.h"
#include "ablib01.h"
void TTest::main_loop()
{
//Questa parte di funzione serve per testare la read, write, delete_node, delete_tree, delete_subtree ecc
TLocalisamfile anas(LF_ANALISI);
anas.set_curr(new TAnalisi_bil());
anas.put(ABAN_CODAN,"A1");
anas.read();
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
TRecnotype nrec = 10; //Per capire quale numero ci va scommenta la riga successiva e provare col debug
//nrec = anas.recno(); //nrec è un TRecnotype: dice quale numero ci va dopo
TLocalisamfile anas1(LF_ANALISI);
anas1.set_curr(new TAnalisi_bil());
anas1.readat(nrec);
//Abilitare solo una di queste funzioni
anas1.remove();
//anas1.write();
E deve esserci solo questo pezzo: tutto il resto deve essere commentato */
}
void ab3100(int argc, char **argv)
{
TTest a;
a.run(argc,argv, "Prova");
}

1003
ab/ablib01.cpp Executable file

File diff suppressed because it is too large Load Diff

342
ab/ablib01.h Executable file
View File

@ -0,0 +1,342 @@
#ifndef __ANALISIB_H
#define __ANALISIB_H
#ifndef __RELATION_H
#define __RELATION_H
#include <relation.h>
#endif //__RELATION_H
#ifndef __APPLICAT_H
#define __APPLICAT_H
#include <applicat.h> //Definizione della classe TApplication
#endif //__APPLICAT_H
#ifndef _ABLI09_H
#define _ABLI09_H
#include "ablib09.h"
#endif //_ABLIB09_H
#ifndef _ANALIS_H
#define _ANALIS_H
#include "analisi.h"
#endif //_ANALIS_H
#ifndef _RELVOCI_H
//#define _RELVOCI_H
#include "relvoci.h"
#endif //_RELVOCI_H
#ifndef _RELANA_H
//#define _RELANA_H
#include "relana.h"
#endif //_RELANA_H
#define TIPO_ANALISI "A"
#define TIPO_VOCE "V"
#define ID_NULLO 0
//Serve per eseguire il test
class TTest: public TSkeleton_application
{
protected:
virtual void main_loop();
public:
// @cmember Costruttore
TTest()
{
}
// @cmember Distruttore
virtual ~TTest()
{
}
};
class TNodeId : public TString
{
};
// classe per un albero navigabile in una direzione
// (depth first o breadth first)
class TAlbero : public TObject
{
protected:
virtual void node2id(const TObject * node,TNodeId & id) const
{return;}
public:
virtual bool empty() {return !goto_root();}
virtual bool goto_root() pure ;
virtual bool goto_firstson() pure ;
virtual bool goto_rbrother() pure ;
virtual TObject * curr_node() const pure ;
void curr_id(TNodeId & var) const
{node2id(curr_node(),var);}
virtual bool goto_node(TNodeId &id)
{return FALSE;}
virtual bool has_son() const
{return FALSE;}
virtual bool has_rbrother() const
{return FALSE;}
TAlbero() {}
virtual ~TAlbero() {}
};
// classe per un albero navigabile in due direzioni
class TAlbero_bidir : public TAlbero
{
public:
virtual bool has_father() const
{return FALSE;}
virtual bool has_lbrother() const
{return FALSE;}
virtual bool goto_father()
{return FALSE;}
virtual bool goto_lbrother()
{return FALSE;}
virtual bool goto_root() {return FALSE;}
virtual bool goto_firstson() {return FALSE;}
virtual bool goto_rbrother() {return FALSE;}
virtual TObject * curr_node() const {return NULL;}
TAlbero_bidir() {}
virtual ~TAlbero_bidir() {}
};
typedef real TRelana_id;
/*class TRelana_id : public real
{
public:
TRelana_id &operator =(const int &v)
{*((real *)this)=v; return *this;}
TRelana_id &operator =(const real &v)
{*((real *)this)=v; return *this;}
TRelana_id(const real &v)
{*this=v;}
TRelana_id()
{}
};*/
//Classe per gestire l'albero di relana
class TAlbero_relana : public TAlbero_bidir
{
TString16 _codtab;
TLocalisamfile *_relana;
TRelana_id _last_id;
protected:
virtual void node2id(const TObject * node,TNodeId & id) const;
public:
// @cmember Ritorna TRUE se riesce a trovare il primo figlio
virtual bool has_son() const;
// @cmember Ritorna TRUE se riesce a trovare il fratello destro
virtual bool has_rbrother() const;
// @cmember Ritorna TRUE se riesce a trovare il padre
virtual bool has_father() const;
// @cmember Ritorna TRUE se riesce a trovare il fratello sinistro
virtual bool has_lbrother() const;
// @cmember Si posiziona sulla radice principale
virtual bool goto_root();
// @cmember Si posiziona sul primo figlio
virtual bool goto_firstson();
// @cmember Si posiziona sul padre
virtual bool goto_father();
// @cmember Si posiziona sul fratello destro
virtual bool goto_rbrother();
// @cmember Si posiziona sul fratello sinistro
virtual bool goto_lbrother();
// @cmember Ritorna TRUE se può posizionarsi sul nodo indicato dall'id specificato
virtual bool goto_node(TNodeId & id)
{return(_relana->readat(atol(id))==NOERR); }
// @cmember Si posiziona sul nodo specificato dall'id
bool goto_id(const TRelana_id &id);
// @cmember Ritorna il nodo corrente
virtual TObject * curr_node() const;
// @cmember Ritorna il nodo corrente
TRectype & curr() {return (TRectype &)*curr_node();}
// @cmember Esegue un lock
bool lock();
// @cmember Esegue un unlock
void unlock();
// @cmember Inserisce un nodo nella struttura ad albero
//bool insert_node(real id);
// @cmember Restituisce un nuovo id (il primo disponibile)
TRelana_id &new_id(real id);
// @cmember Costruttore
TAlbero_relana( const char * tabcode);
// @cmember Distruttore
virtual ~TAlbero_relana();
};
//Classe per gestire la struttura di una tabella di analisi
// basandosi sull'albero di relvoci
class TAlbero_relvoci : public TAlbero
{
TString16 _codtab;
TLocalisamfile *_relvoci;
protected:
virtual void node2id(const TObject * node, TNodeId & id) const;
public:
// @cmember Si posiziona sulla radice principale
virtual bool goto_root();
// @cmember Ritorna TRUE se trova un figlio
virtual bool has_son() const;
// @cmember Si posiziona sul primo figlio
virtual bool goto_firstson();
// @cmember Ritorna TRUE se trova un fratello destro
virtual bool has_rbrother() const;
// @cmember Si posiziona sul fratello destro
virtual bool goto_rbrother();
// @cmember Ritorna TRUE se trova un fratello sinistro
bool has_lbrother() const;
// @cmember Si posiziona sul fratello sinistro
bool goto_lbrother();
// @cmember Restituisce il nodo corrente
virtual TObject * curr_node() const;
// @cmember Restituisce il nodo specificato dall'id
virtual bool goto_node(TNodeId & id)
{return (_relvoci->readat(atol(id))==NOERR);}
// @cmember Restituisce il nodo corrente
TRectype & curr() {return (TRectype &)*curr_node();}
// @cmember Esegue un lock
bool lock();
// @cmember Esegue un unlock
void unlock();
// @cmember Restituisce il codice della tabella che si sta usando
const TString & codtab()
{return _codtab;}
// @cmember Costruttore
TAlbero_relvoci(const char * tabcode);
// @cmember Distruttore
virtual ~TAlbero_relvoci() ;
};
// Struttura da albero basata su un file temporaneo cached
class TInsert_albero : public TAlbero_bidir
{
TRWrecord_cache * _ana_cache;
TLocalisamfile *_f; // da rimuovere !!
TRectype *_currnode;
TRelana_id _last_insert_id;
TAssoc_array _status_node;
// debug
void write_cache() { _ana_cache->flush(); }
protected:
// @cmember Elimina il sottoalbero dei figli di un nodo
// @cmember che sta per essere eliminato da un struttura di tipo lista doppiamente lincata
bool remove_subtree(const TRelana_id lastnode_id);
// @cmember genera/setta il nuovo id
TRelana_id &new_id(TRelana_id);
void goto_node(const TRelana_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;}
public:
// @cmember Inserisce un nodo in una struttura di tipo lista doppiamente lincata
bool insert_node(TRectype &node, const TRelana_id id_prec, const TRelana_id id_padre, TRelana_id id);
// @cmember Elimina un nodo da una struttura di tipo lista doppiamente lincata
bool delete_node(const TRelana_id &id);
// @cmember Lancia la rimozione di tutto l'albero
bool delete_tree();
// @cmember Lancia la rimozione di tutto l'albero
void zero();
// @cmember Restituisce il nodo corrente
TRectype * current() const {return (TRectype * )_currnode;}
// @cmember Restituisce TRUE se esiste un figlio di un nodo
virtual bool has_son();
// @cmember Si posizione sul primo figlio di un nodo
virtual bool goto_firstson();
// @cmember Restituisce TRUE se esiste il fratello destro di un nodo
virtual bool has_rbrother();
// @cmember Si posiziona sul fratello destro di un nodo
virtual bool goto_rbrother();
// @cmember Si posiziona sul primo nodo della struttura ad albero
virtual bool goto_root();
// @cmember Restituisce il nodo corrente
virtual TObject * curr_node() const {return _currnode;}
// ***** gestione interfaccia Database/copia locale
// @cmember Estrae un nodo dall'albero
TRectype extract_node(const TString &codtab,TRelana_id &id, TString& status);
// @cmember Ritorna il numero di elementi dell'assoc_array status_node
int status_node_items() { return _status_node.items();}
// @cmember Setta lo stato del nodo: valori ammessi = nodo <A>ggiunto, nodo <M>odificato, nodo <R>imosso
void set_status_node(const TRelana_id &id, const char *status);
// @cmember Ritorna lo stato di un nodo
const char* get_status_node(const TRelana_id &id);
// @cmember Costruttore
TInsert_albero();
// @cmember Distruttore
virtual ~TInsert_albero();
};
class TAnalisi_bil: public TRectype
{
class TArray_fratelli: public TAssoc_array
{
public:
void setkey(const char *tipocod, const char *codvc, TToken_string &key) const;
bool find1stkey(const char *tipocod, const char *codvc, TToken_string &key);
void mark_used(const char *key);
bool used(TObject *o);
};
TArray_fratelli _nodifratelli;
TLocalisamfile *_analisi;
TLocalisamfile *_voci;
TAlbero_relvoci *_relaz;
TAlbero_relana *_ana;
TInsert_albero *_inter_tree;
TRectype * _newrec; //buffer per l'inserimento dodo per nodo
protected:
// @cmember Esegue una navigazione dell'albero di rel_voci e di rel_ana
// @cmember parallelamente verificanto eventualmente delle inconsistenze
void naviga_relazioni(const TRelana_id & id_relana,const TRelana_id & prec,const TRelana_id & padre );
// @cmember Sincronizza la copia locale basandosi su relvoci (per la struttura) e su relana (per le info aggiuntive)
TRectype * sincronizza_relana(const TRelana_id &begin_relana,TRelana_id &id_relana);
// @cmember Esegue un lock di una struttura ad albero
bool lock_struttura();
// @cmember Esegue un unlock di una struttura ad albero
bool unlock_struttura();
// @cmember Esegue un lock su una tabella di analisi
bool lock_tabella();
// @cmember Sblocca una tabella di analisi
bool unlock_tabella();
public:
// @cmember Costruttore
TAnalisi_bil();
// #cmember Distruttore
virtual ~TAnalisi_bil() ;
// @cmember Ritrona il tipo di analisi
const TString &type() {return get(ABAN_TIPOAN);}
// @cmember Setta il tipo di analisi
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;}
};
#endif //__ANALISI_H

148
ab/ablib09.cpp Executable file
View File

@ -0,0 +1,148 @@
///////////////////////////////////////////////////////////
// Cache
///////////////////////////////////////////////////////////
#include "ablib09.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();
}
//Scarica una parte della cache
void TRWrecord_cache::discard(const TString & vittima)
{
if (items()) //Usa l'items di TFile_cahe che richiame l'items dell'assoc_array _cache
{
if (_flags.is_key(vittima)) //_flags è un assoc_array di TRWcache, usa is_key di assoc_array
{
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);
}//Se non esiste nel assoc_array di TRWcache
_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());
}
//Vuota una cache
void TRWrecord_cache::clear()
{
while (items()>0)
{
const TString & vittima=getkey2discard();
if (_flags.is_key(vittima))
_flags.remove(vittima);
_cache.remove(vittima);
}
}
//Forza la scrittura sulla cache
void TRWrecord_cache::flush()
{
while (items()>0)
{
discard(TRWrecord_cache::getkey2discard());
}
}
THash_object * TRWrecord_cache::get_some_obj()
{
if (items()==0) //Usa l'items() di TFilecache fa items() di un assoc_array _cahce
return NULL;
THash_object * o;
while ((o=_cache.get_hashobj()) == NULL) ; //Ritorna l'oggetto e la relativa chiave dell'assoc_array _cache
return o;
}
//Costruttori vari
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();
}

24
ab/ablib09.h Executable file
View File

@ -0,0 +1,24 @@
#ifndef _RECARRAY_H
#include <recarray.h>
#endif
class TRWrecord_cache : public TRecord_cache
{
TAssoc_array _flags;
protected:
THash_object * get_some_obj();
virtual const TString & getkey2discard();
public:
virtual void discard(const TString & k);
virtual void put(const TRectype &r);
virtual const TRectype& get(const char* chiave);
void clear();
void flush();
TRWrecord_cache(TLocalisamfile *f, int key = 1, bool lock=FALSE);
TRWrecord_cache(int num, int key = 1, bool lock=FALSE);
TRWrecord_cache(const char* table, int key = 1, bool lock=FALSE);
virtual ~TRWrecord_cache() ;
};