From 2c2d9722162d6cba18ec56d60cd3d318fce29470 Mon Sep 17 00:00:00 2001 From: guy Date: Mon, 30 Mar 1998 13:50:30 +0000 Subject: [PATCH] prefix.* Migliorata gestione handles dei file aperti progind.cpp Corretta gestione messaggi multiriga per XI_R4 progind.h Trasformate da void a bool i metodi setstatus e addstatus rectypes.h Aggiunti due nuovi TDirtype _studir e extdir relapp.cpp Migliorata gestione stringhe fisse relation.cpp Adeguati i cursori alla nuova gestione handles relation.h Tolto _filename dai cursori e messo _indexfirm git-svn-id: svn://10.65.10.50/trunk@6457 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- include/prefix.cpp | 820 +++++++++++++++++++++++++++++++++++++------ include/prefix.h | 91 ++++- include/progind.cpp | 45 ++- include/progind.h | 9 +- include/rectypes.h | 10 +- include/relapp.cpp | 4 +- include/relation.cpp | 113 +++--- include/relation.h | 4 +- 8 files changed, 902 insertions(+), 194 deletions(-) diff --git a/include/prefix.cpp b/include/prefix.cpp index c2c17d120..ff03017c8 100755 --- a/include/prefix.cpp +++ b/include/prefix.cpp @@ -1,5 +1,6 @@ #include #include + #include #include #include @@ -8,27 +9,17 @@ #include +// Definita in isam.cpp extern int get_error(int); /////////////////////////////////////////////////////////// // extern variables are NO-NO! /////////////////////////////////////////////////////////// -HIDDEN TString16 _user; HIDDEN TPrefix* _prefhndl = NULL; // @doc EXTERNAL -// @func Ritorna il nome dell'utente attuale -// -// @rdesc Ritorno il nome dell'utente attuale -TString& user() -{ - return _user; -} - -// @doc EXTERNAL - // @func Inizializza (crea) un nuovo file "prefix.txt" // // @rdesc Ritorna l'oggetto creato @@ -62,6 +53,689 @@ void prefix_destroy() } } +/////////////////////////////////////////////////////////// +// TFile_manager +/////////////////////////////////////////////////////////// + +class TRecord_info : public TObject +{ + RecDes _recdes; + TDirtype _dirtype; + int _len; + +protected: + void translate_key(TToken_string& t) const; + void compute_len(); + + bool create(TTrec& rec, TToken_string& keys); + +public: // TObject + virtual bool ok() const; + +public: + operator const RecDes&() const { return _recdes; } + int len() const { return _len; } + + TDirtype dir_type() const { return _dirtype; } + bool mutable_dir() const { return _dirtype <= _studir; } + bool fixed_dir() const { return _dirtype > _studir; } + + TRecord_info(int logicnum); + TRecord_info(const char* name); + TRecord_info(TTrec& rec, TToken_string& keys); + virtual ~TRecord_info() { } +}; + +void TRecord_info::translate_key(TToken_string& t) const// Traduce l'espressione chiave di CodeBase +{ + // Trasforma l'espressione + TToken_string k(t.get(0),'+'); + TToken_string range("",','); + TString ws; + const bool is_dup = t.get(1)[0] == 'X'; + const int items = k.items(); + t = ""; + for (int i = 0; i= 0; + const bool is_sub = ws.find("SUBSTR") >= 0; + int paren1 = ws.find('('); // Trova la prima parentesi aperta + int paren2,last,from,to; + + if (paren1 >= 0 && is_sub && is_upper) + paren1 = ws.find('('); // Trova la seconda parentesi (in questo caso c'e' per forza) + + if (paren1 >= 0) // Trova la prima virgola o parentesi chiusa (per qualsiasi espressione) + { + paren2 = ws.find(','); + if (paren2 == -1) // se non ci sono virgole trova la parentesi chiusa + paren2 = ws.find(')'); + CHECK(paren2 > paren1,"Something wrong happened translating CodeBase expressions."); + if (is_sub) // Se e' una sottostringa estrae i campi DA e A + { + range = ws; + last = ws.find(')'); + range.sub(paren2,last); // dalla virgola alla parentesi + from = range.get_int(0); + to = range.get_int(1); + } + ws = ws.sub(paren1+1,paren2); // Nome del campo pulito pulito + ws.upper(); + } + + if (is_upper) + t << "UPPER("; + + t << ws; // aggiunge il nome del campo + + if (is_sub) + { + t << "["; + t << from << ","; + t << to << "]"; + } + if (is_upper) + t << ")"; + t << '+'; + } + t.rtrim(1); // Toglie il + in piu' + t.add(is_dup ? "X" : " "); +} + +bool TRecord_info::ok() const +{ + return _recdes.NFields > 0 && + _recdes.NKeys > 0 && _recdes.NKeys < MaxKeys; +} + +void TRecord_info::compute_len() +{ + _len = 0; + for (int f = _recdes.NFields-1; f >= 0; f--) + _len += _recdes.Fd[f].Len; + if (_len > 0) + _len++; +} + +TRecord_info::TRecord_info(int logicnum) +{ + memset(&_recdes, 0, sizeof(_recdes)); + + FileDes fd; memset(&fd, 0, sizeof(fd)); + CGetFile(logicnum, &fd, _nolock, _nordir); + if (fd.SysName[0]) + { + _dirtype = fd.SysName[0] != '$' ? _comdir : _nordir; + CGetRec(logicnum, &_recdes, _dirtype); + } + if (ok()) + compute_len(); +} + +bool TRecord_info::create(TTrec& rec, TToken_string& keys) +{ + rec.rehash(); + const int num_keys = rec.keys(); + + TToken_string trans; + for (int i = 0; i < num_keys; i++) + { + trans = keys.get(i); + translate_key(trans); // Traduce l'espressione chiave di CodeBase + rec.update_keydef(i, trans); + } + memcpy(&_recdes, rec.rec(), sizeof(RecDes)); + compute_len(); + return _len > 0; +} + +TRecord_info::TRecord_info(TTrec& rec, TToken_string& keys) + : _dirtype(_extdir) +{ + create(rec, keys); +} + +TRecord_info::TRecord_info(const char* name) + : _dirtype(_extdir) +{ + TFilename fname(name); fname.ext("dbf"); + if (fname.exist()) + { + TToken_string keys(256*MaxKeys, '$'); + + fname.ext(""); + FileDes fd; + TTrec rec; + int err = DB_recinfo(fname, &fd, rec.rec(), keys.get_buffer()); + if (err != NOERR) + create(rec, keys); + else + memset(&_recdes, 0, sizeof(_recdes)); + } + else + memset(&_recdes, 0, sizeof(_recdes)); +} + + +class TFile_info : public TObject +{ + TFilename _name; + int _ref_count; + + int _num; + int _handle; + clock_t _last_access; + bool _locked, _exclusive; + TDirtype _dir; + FileDes _filedes; + + int _last_key; + +protected: + int open_low(bool exclusive, bool index); + int close_low(); + +public: // TObject + virtual bool ok() const { return _name.not_empty(); } + +public: + const TFilename& pathname() const { return _name; } + int num() const { return _num; } + int handle() const { return _handle; } + bool is_open() const { return _handle >= 0; } + clock_t last_access() const { return _last_access; } + bool is_exclusive() const { return _exclusive; } + bool is_locked() const { return _locked; } + int ref_count() const { return _ref_count; } + int last_key() const { return _last_key; } + void touch() { _last_access = clock(); } + + TDirtype dir_type() const { return _dir; } + bool mutable_dir() const { return _dir <= _studir; } + bool fixed_dir() const { return _dir > _studir; } + + int open(bool exclusive, bool index); + int close(); + const TFilename& load_filedes(); + + void lock_record(TRecnotype rec); + void unlock_record(TRecnotype rec); + + int auto_open(int key); + void auto_close(); + + operator const FileDes&() const { return _filedes; } + TFile_info(int logicnum, TFilename& name); + virtual ~TFile_info(); +}; + + +int TFile_info::open_low(bool exclusive, bool index) +{ + if (_handle < 0) + _handle = DB_open(_name, exclusive, index); +#ifdef DBG + else + NFCHECK("Can't reopen file %s", (const char*)_name); +#endif + int err = NOERR; + if (_handle >= 0) + { + if (num() < LF_EXTERNAL && (_dir == _nordir || _dir == _comdir)) + { + TRecnotype n = DB_reccount(_handle); + TDir d; + d.get(num(),_nolock,_dir,_sysdirop); + _filedes.EOD = d.eod() = n; + _filedes.EOX = d.eox() = n; + d.put(num(),_dir,_sysdirop); + } + } + else + { + err = get_error(_handle); + } + return err; +} + +int TFile_info::close_low() +{ + int err = NOERR; + if (_handle >= 0) + { + DB_close(_handle); + _handle = -1; + } + else + { +#ifdef DBG + NFCHECK("Can't reclose file %s", (const char*)_name); +#endif + err = _isnotopen; + } + return err; +} + +int TFile_info::open(bool exclusive, bool index) +{ + int err = NOERR; + if (exclusive || !index) + { + if (_ref_count > 0 || is_open()) + { +#ifdef DBG + NFCHECK("Can't reopen file %d exclusively", _num); +#endif + close_low(); + } + _exclusive = _locked = TRUE; + err = open_low(exclusive, index); + } + _ref_count++; + return err; +} + +int TFile_info::close() +{ + int err = NOERR; + if (_ref_count > 0) + { + _ref_count--; + if (_ref_count == 0) + { + if (is_open()) + err = close_low(); + _locked = _exclusive = FALSE; + _last_key = -1; + } + } + else + err = _isnotopen; + return err; +} + +void TFile_info::auto_close() +{ + const bool yes = is_open() && !is_locked() && !is_exclusive(); + if (yes) + close_low(); + else + NFCHECK("Can't auto_close file '%s'", (const char*)_name); +} + +int TFile_info::auto_open(int key) +{ + if (_handle < 0) + { + open_low(FALSE, TRUE); + } + + if (_handle >= 0) + { + if (key > 0 && key != _last_key) + { + const int err = DB_tagselect(_handle, _last_key = key); + if (err != NOERR) + { +#ifdef DBG + NFCHECK("Can't set key %d on file %d", key, num()); +#endif + return err; + } + } + } + return _handle; +} + +void TFile_info::lock_record(TRecnotype) +{ _locked = TRUE; } + +void TFile_info::unlock_record(TRecnotype) +{ _locked = FALSE; } + +const TFilename& TFile_info::load_filedes() +{ + memset(&_filedes, 0, sizeof(_filedes)); + CGetFile(num(), &_filedes, _nolock, _nordir); + if (_filedes.SysName[0]) + { + if (_filedes.SysName[0] != '$') + _dir = _comdir; + else + _dir = _nordir; + COpenFile(num(), &_filedes, _nolock, _dir); + _name = _filedes.SysName; + } + else + _name.cut(0); + return _name; +} + +TFile_info::TFile_info(int logicnum, TFilename& name) +: _num(logicnum), _handle(-1), _ref_count(0), + _locked(FALSE), _exclusive(FALSE), + _last_access(0), _last_key(-1) +{ + if (logicnum < LF_EXTERNAL) + { + load_filedes(); + if (name.not_empty()) + { + // File dati temporaneo + _dir = _extdir; + _name = name; + _name.ext(""); + } + else + name = _name; + } + else + { + // File dati esterno + _dir = _extdir; + _name = name; + _name.ext("dbf"); + if (_name.exist()) + { + TToken_string keys(256*MaxKeys, '$'); + + _name.ext(""); + TTrec rec; + int err = DB_recinfo(_name, &_filedes, rec.rec(), keys.get_buffer()); + if (err == NOERR && prefix().add_recdes(logicnum, rec, keys)) + { + strncpy(_filedes.SysName, _name, 40); + _filedes.SysName[41] = '\0'; + } + else + _name.cut(0); + } + else + _name.cut(0); + } +} + + +TFile_info::~TFile_info() +{ + if (is_open()) + close_low(); +} + + +TFile_info& TFile_manager::fileinfo(TIsam_handle num) +{ + TFile_info* i = (TFile_info*)_fileinfo.objptr(num); + if (i == NULL && num > 0 && num < LF_EXTERNAL) + { + TFilename name; + i = new TFile_info(num, name); + if (i->ok()) + _fileinfo.add(i, num); + else + { + delete i; + i = NULL; + } + } + + CHECKD(i, "Unknown file ", num); + return *i; +} + +TRecord_info& TFile_manager::recinfo(int logicnum) +{ + TRecord_info* i = (TRecord_info*)_recinfo.objptr(logicnum); + if (i == NULL) + { + i = new TRecord_info(logicnum); + _recinfo.add(i, logicnum); + } + return *i; +} + +bool TFile_manager::add_recdes(int logicnum, TTrec& rec, TToken_string& keys) +{ + TRecord_info* i = (TRecord_info*)_recinfo.objptr(logicnum); + if (i == NULL) + { + if (logicnum < LF_EXTERNAL) + i = new TRecord_info(logicnum); + else + i = new TRecord_info(rec, keys); + if (i->ok()) + _recinfo.add(i, logicnum); + else + { + delete i; + i = NULL; + } + } + return i != NULL; +} + + +bool TFile_manager::close_oldest() +{ + int oldest = 0; + clock_t age = 0; + + for (int n = _fileinfo.last(); n > 0; n = _fileinfo.pred(n)) + { + TFile_info& i = (TFile_info&)_fileinfo[n]; + if (i.is_open() && !i.is_locked() && !i.is_exclusive()) + { + if (oldest == 0 || i.last_access() < age) + { + oldest = n; + age = i.last_access(); + } + } + } + if (oldest) + { + TFile_info& i = (TFile_info&)_fileinfo[oldest]; + i.auto_close(); + _open_files--; + } + + return oldest != NULL; +} + +// name : nome del file (vuoto per i file normali viene riempito automaticamente) +// logicnum: numero logico del file (LF_EXTERNAL per gli esterni viene generato automaticamente) +TIsam_handle TFile_manager::open(int& logicnum, TFilename& name, bool exclusive, bool index) +{ + TIsam_handle num = logicnum; + if (name.not_empty()) + { + TFile_info* i = NULL; + for (num = LF_EXTERNAL; (i = (TFile_info*)_fileinfo.objptr(num)) != NULL; num++) + { + if (i->pathname() == name) + break; + } + if (logicnum >= LF_EXTERNAL) + logicnum = num; + } + + TFile_info* i = (TFile_info*)_fileinfo.objptr(num); + if (i == NULL) + { + i = new TFile_info(logicnum, name); + if (!i->ok()) + { + delete i; + return -60; + } + _fileinfo.add(i, num); + } + i->open(exclusive, index); + name = i->pathname(); + return num; +} + +int TFile_manager::close(TIsam_handle& name) +{ + int err = _isnotopen; + + TFile_info* i = (TFile_info*)_fileinfo.objptr(name); + if (i != NULL) + { + err = i->close(); + if (err == NOERR && i->ref_count() == 0) + { + if (name >= LF_EXTERNAL) + { + _fileinfo.remove(name); + _recinfo.remove(name); + } + } + } + name = 0; + return err; +} + +TCodeb_handle TFile_manager::get_handle(TIsam_handle name, int key) +{ + TFile_info& i = fileinfo(name); + if (i.ref_count() == 0) + NFCHECK("Can'use not open file %d", i.num()); + + TCodeb_handle handle = i.handle(); + if (handle < 0) + { + if (_open_files >= _max_open_files) + close_oldest(); + + handle = i.auto_open(key); + if (handle >= 0) + _open_files++; + } + else + { + if (i.last_key() != key) + handle = i.auto_open(key); + } + i.touch(); + return handle; +} + +void TFile_manager::lock_record(TIsam_handle num, TRecnotype rec) +{ + TFile_info& i = fileinfo(num); + i.lock_record(rec); +} + +void TFile_manager::unlock_record(TIsam_handle num, TRecnotype rec) +{ + TFile_info& i = fileinfo(num); + i.unlock_record(rec); +} + + +const RecDes& TFile_manager::get_recdes(int logicnum) +{ + const TRecord_info& i = recinfo(logicnum); + return i; +} + +const RecDes& TFile_manager::update_recdes(int logicnum) +{ + _recinfo.destroy(logicnum); + return get_recdes(logicnum); +} + +int TFile_manager::get_reclen(int logicnum) +{ + const TRecord_info& i = recinfo(logicnum); + return i.ok() ? i.len() : 0; +} + +TDirtype TFile_manager::get_dirtype(int logicnum) +{ + const TRecord_info& i = recinfo(logicnum); + return i.dir_type(); +} + +int TFile_manager::close_closeable() +{ + _open_files = 0; + for (TIsam_handle n = _fileinfo.last(); n > 0; n = _fileinfo.pred(n)) + { + TFile_info& i = fileinfo(n); + if (i.ref_count() > 0) + { + if (i.is_open()) + { + if (!i.is_locked() && !i.is_exclusive()) + i.auto_close(); + else + _open_files++; + } + } + else + { +#ifdef DBG + if (i.is_open()) + { + NFCHECK("File %d is open without references?", i.num()); + _open_files++; + } + else +#endif + _fileinfo.destroy(n); + } + } + return _open_files; +} + +void TFile_manager::close_all() +{ + const int zoccolo_duro = close_closeable(); + if (zoccolo_duro > 0) + NFCHECK("%d files refuse to be closed!", zoccolo_duro); + + for (int n = _recinfo.last(); n > 0; n = _recinfo.pred(n)) + { + const TRecord_info& r = recinfo(n); + if (r.mutable_dir()) + _recinfo.destroy(n); + } +} + +void TFile_manager::open_all() +{ + for (TIsam_handle n = _fileinfo.last(); n > 0; n = _fileinfo.pred(n)) + { + TFile_info& i = fileinfo(n); + if (!i.is_exclusive()) + { + if (i.mutable_dir()) + i.load_filedes(); + } + } +} + +const FileDes& TFile_manager::get_filedes(TIsam_handle name) +{ + TFile_info& i = fileinfo(name); + return i; +} + +TFile_manager::TFile_manager() + : _open_files(0) +{ + TConfig prawin(CONFIG_INSTALL, "Main"); + _max_open_files = prawin.get_int("MaxHandles", NULL, 16); + if (_max_open_files < 8) + _max_open_files = 8; + else + if (_max_open_files > 32) + _max_open_files = 32; +} + /////////////////////////////////////////////////////////// // TPrefix /////////////////////////////////////////////////////////// @@ -75,107 +749,28 @@ TPrefix::TPrefix() : _filelevel(0), _items(0) const TFilename dir(cprefix); const long primaditta = atol(dir.name()); - if (primaditta > 0 && !exist(primaditta)) - set("com", TRUE); + if (primaditta > 0L && !exist(primaditta)) + set_codditta(0L, TRUE); + + DB_init(); } TPrefix::~TPrefix() { set(); + DB_exit(); } - -HIDDEN int closeall(bool changestudy, TBit_array& excl, TBit_array& toclose) -{ - if (!openf) return 0; - TDir d; - d.get(1); - const int max = (int) d.eod(); - - int err = NOERR; - - for (int i = 1; i < max; i++) - if (openf[i] != NULL) - { - isfdptr isfd = openf[i]; - d.get(i + 1, _nolock, _nordir, _sysdirop); - if (toclose[i + 1] || changestudy || !d.is_com()) - { - excl.set(i, DB_file_locked(isfd->fhnd) != 0); - err=DB_close(isfd->fhnd); - if (err != NOERR) err=get_error(err); - if (err != NOERR) fatal_box("Can't close file %d. Error n. %d",isfd->ln,err); - exclunlock(CInsPref((char*) glockname, _nordir), FALSE); - } - } - return max; -} - - -HIDDEN void openall(bool changestudy, TBit_array& excl, int oldmax, TBit_array& toopen) -{ - if (!openf) - return ; - TDir d; - d.get(1); - const int max = (int) d.eod(); - - for (int i = max; i < oldmax; i++) - if (openf[i] != NULL) - { - d.get(i + 1, _nolock, _nordir, _sysdirop); - if (changestudy || !d.is_com()) - fatal_box("Can't reopen file n. %d", i + 1); - } - - int err = NOERR; - - for (i = 1; i < max; i++) - if (openf[i] != NULL) - { - isfdptr isfd = openf[i]; - d.get(i + 1, _nolock, _nordir, _sysdirop); - const bool com = d.is_com(); - if (toopen[i + 1] || changestudy || !com) - { - isfd->ft = com ? _comdir : _nordir; - d.get(i + 1, _nolock, (TDirtype) isfd->ft); - *isfd->d = *d.filedesc(); - - TTrec r; - r.get(i + 1, (TDirtype) isfd->ft); - *isfd->r = *r.rec(); - if (excllock(CInsPref((char*) glockname, NORDIR), FALSE) == -1) - fatal_box("Can't reopen file n. %d : file in use", i + 1); - isfd->fhnd = DB_open(isfd->d->SysName, excl[i],TRUE); - if (isfd->fhnd < 0 ) err=get_error(isfd->fhnd); - else err = NOERR; - if (err == _islocked) - fatal_box("Can't reopen file n. %d : file in use", i + 1); - if (err != NOERR) - fatal_box("Can't reopen file n. %d : error n. %d", i + 1, err); - } - } -} - // @doc EXTERNAL // @mfunc Riapre tutti gli archivi della ditta attiva void TPrefix::reopen() const - { if (_prefix != ".") { - TBit_array excl, comfiles; - comfiles.set(LF_PCON); - comfiles.set(LF_CLIFO); - comfiles.set(LF_INDSP); - comfiles.set(LF_CAUSALI); - comfiles.set(LF_RCAUSALI); - int max = closeall(FALSE, excl, comfiles); - - openall(FALSE, excl, max, comfiles); + ((TPrefix*)this)->_manager.close_all(); + ((TPrefix*)this)->_manager.open_all(); } } @@ -204,21 +799,13 @@ void TPrefix::set( return; } - if (_prefix == name) return; - - if (!force && !test(name)) return; - - TBit_array excl, comfiles; - int max = 0; - comfiles.set(LF_PCON); - comfiles.set(LF_CLIFO); - comfiles.set(LF_INDSP); - comfiles.set(LF_CAUSALI); - comfiles.set(LF_RCAUSALI); - + if (_prefix == name) + return; + if (!force && !test(name)) + return; if (_prefix != ".") { - max = closeall(FALSE, excl, comfiles); + _manager.close_all(); CCloseDir(NORDIR); CCloseDir(COMDIR); CCloseRecDir(NORDIR); @@ -249,11 +836,10 @@ void TPrefix::set( if (_prefix != ".") { FileDes d; - CGetFile(LF_DIR, &d, _nolock, NORDIR); _filelevel = d.Flags; _items = (int)d.EOD; - openall(FALSE, excl, max, comfiles); + _manager.open_all(); } } @@ -287,6 +873,16 @@ bool TPrefix::test(const char* s) const return TRUE; } +void TPrefix::lock_record(TIsam_handle num, TRecnotype rec) +{ + _manager.lock_record(num, rec); +} + +void TPrefix::unlock_record(TIsam_handle num, TRecnotype rec) +{ + _manager.unlock_record(num, rec); +} + bool TPrefix::test(long codditta) const { TString16 s("com"); diff --git a/include/prefix.h b/include/prefix.h index cb474f843..0f03652af 100755 --- a/include/prefix.h +++ b/include/prefix.h @@ -1,14 +1,62 @@ #ifndef __PREFIX_H #define __PREFIX_H +#ifndef __EXTCTYPE_H +#include +#endif + #ifndef __RECTYPES_H #include #endif -#ifndef __STRINGS_H -#include +#ifndef __ASSOC_H +#include #endif +class TFile_info; +class TRecord_info; +class TTrec; + +typedef int TIsam_handle; +typedef int TCodeb_handle; + +class TFile_manager : public TObject +{ + TArray _fileinfo; + TArray _recinfo; + int _open_files, _max_open_files; + +protected: + TFile_info& fileinfo(TIsam_handle handle); + TRecord_info& recinfo(int logicnum); + + bool close_oldest(); + +public: + TIsam_handle open(int& logicnum, TFilename& name, bool excl, bool idx); + int close(TIsam_handle& name); + + void lock_record(TIsam_handle num, TRecnotype rec); + void unlock_record(TIsam_handle num, TRecnotype rec); + + const FileDes& get_filedes(TIsam_handle name); + const RecDes& get_recdes(int logicnum); + const RecDes& update_recdes(int logicnum); + TDirtype get_dirtype(int logicnum); + bool add_recdes(int logicnum, TTrec& rec, TToken_string& keys); + + TCodeb_handle get_handle(TIsam_handle name, int key); + int get_reclen(int logicnum); + + int close_closeable(); + void close_all(); + void open_all(); + + TFile_manager(); + virtual ~TFile_manager() { } +}; + + // @doc EXTERNAL // @class TPrefix | Classe contenente le informazioni sulla ditta correntemente in uso @@ -27,6 +75,8 @@ class TPrefix : public TObject long _filelevel; // @cmember:(INTERNAL) Numero di files esitenti int _items; + + TFile_manager _manager; // @access Protected Member protected: @@ -74,7 +124,40 @@ public: bool build_firm_data(long codditta, bool flagcom = FALSE); // @cmember Riapre tutti gli archivi della ditta attiva void reopen() const ; - + + TIsam_handle open_isamfile(int& logicnum, TFilename& name, bool excl = FALSE, bool idx = TRUE) + { return _manager.open(logicnum, name, excl, idx); } + + int close_isamfile(TIsam_handle& name) + { return _manager.close(name); } + + void lock_record(TIsam_handle num, TRecnotype rec); + void unlock_record(TIsam_handle num, TRecnotype rec); + + int close_closeable_isamfiles() + { return _manager.close_closeable(); } + + TDirtype get_dirtype(TIsam_handle name) + { return _manager.get_dirtype(name); } + + int get_handle(TIsam_handle name, int key = 0) + { return _manager.get_handle(name, key); } + + const RecDes& get_recdes(int logicnum) + { return _manager.get_recdes(logicnum); } + + bool add_recdes(int logicnum, TTrec& rec, TToken_string& keys) + { return _manager.add_recdes(logicnum, rec, keys); } + + const RecDes& update_recdes(int logicnum) + { return _manager.update_recdes(logicnum); } + + int get_reclen(int logicnum) + { return _manager.get_reclen(logicnum); } + + const FileDes& get_filedes(TIsam_handle name) + { return _manager.get_filedes(name); } + // @cmember Costruttore TPrefix(); // @cmember Distruttore @@ -84,8 +167,6 @@ public: const char* firm2dir(long codditta); -TString& user(); - TPrefix& prefix_init(); TPrefix& prefix(); void prefix_destroy(); diff --git a/include/progind.cpp b/include/progind.cpp index 4dfbcd700..bb5b0b6af 100755 --- a/include/progind.cpp +++ b/include/progind.cpp @@ -46,8 +46,7 @@ TIndwin::TIndwin(long max, const char* txt, bool cancel, bool bar, int div) _text = new TMultiline_control(win(), DLG_NULL, 1, 1, hor-2, lines+1, 512, "CD", ""); _text->set_read_only(); - testo.replace('\n', '\r'); - _text->set_caption(testo); + set_text(testo); if (bar) { @@ -72,9 +71,21 @@ void TIndwin::set_text( // @comm Si puo' chiamare questa funzione per cambiare il testo, ma // le dimensioni della finestra sono calcolate sul primo testo // passato, quindi occorre dimensionare correttamente il primo passato - // (es. inserire degli spazi) se se ne prevede uno piu' lungo. + // (es. inserire degli spazi) quando se ne prevede uno piu' lungo. { +#ifdef XI_R4 _text->set_caption(t); +#else + TString testo(t); + testo.replace('\n', '\r'); + _text->set_caption(testo); +#endif + + if (_bar) + { + RCT r; get_bar_rct(r); + xvt_dwin_invalidate_rect(win(), &r); + } } TIndwin::~TIndwin() @@ -104,6 +115,16 @@ KEY TIndwin::check_stop() return k; } +RCT* TIndwin::get_bar_rct(RCT& r) const +{ + xvt_vobj_get_client_rect(win(), &r); + r.left += CHARX; + r.right -= CHARX; + r.top = (int)_bar; + r.bottom = r.top + 2*CHARY; + return &r; +} + void TIndwin::update_bar() { if (_status >= _max) @@ -116,13 +137,10 @@ void TIndwin::update_bar() const double prc = (double)_status/_max; WINDOW w = win(); - RCT r; xvt_vobj_get_client_rect(w, &r); - - // Rettangolo contenente l'intera barra - r.left += CHARX; r.right -= CHARX; - r.top = (int)_bar; - r.bottom = r.top + 2*CHARY; + // Rettangolo contenente l'intera barra + RCT r; get_bar_rct(r); + RCT b = r; if (CAMPI_SCAVATI) @@ -151,7 +169,7 @@ void TIndwin::update_bar() char n[8]; sprintf(n, "%d%%", int(prc * 100.0 + 0.5)); xvt_dwin_draw_text(w, r.left+r.right/2-CHARX, (r.bottom+r.top+CHARY)/2-3, n, -1); - + check_stop(); } @@ -183,16 +201,19 @@ TProgind::TProgind(long max, const char* txt, bool cancel, bool bar, int div) : TIndwin(max, txt, cancel, bar, div) {} -void TProgind::setstatus(long l) +bool TProgind::setstatus(long l) { + CHECK(l >= 0, "Bad progind status"); const long old_perc = _status * 100L / _max; _status = l > _max ? _max : l; const long new_perc = _status * 100L / _max; - if (new_perc > old_perc) + const bool tictac = new_perc != old_perc; + if (tictac) { update_bar(); do_events(); } + return tictac; } // TTimerind ------------------------------------------------------------ diff --git a/include/progind.h b/include/progind.h index 3e1a6cd23..b8ae74206 100755 --- a/include/progind.h +++ b/include/progind.h @@ -50,6 +50,9 @@ protected: // @cmember Ritorna il numero di linee necessarie per scrivere il testo nella finestra word measure_text(TToken_string& t, word& len) const; + // @cmember Calcola il rettangolo della barra di attesa + RCT* get_bar_rct(RCT& r) const; + // @cmember Gestisce gli eventi tasto della finestra virtual bool on_key(KEY k); @@ -105,10 +108,10 @@ public: void setmax(long m) { _max = m; } // @cmember Setta lo stato della barra d'attesa - void setstatus(long l); + bool setstatus(long l); // @cmember Aggiorna la barra d'attesa aggiungendo l'incremento fatto dell'applicazione - void addstatus(long l) - { setstatus(_status+l); } + bool addstatus(long l) + { return setstatus(_status+l); } // @cmember Costruttore TProgind(long max, const char* txt = NULL, bool cancel = TRUE, bool bar = TRUE, int div = 60); // @cmember Distruttore diff --git a/include/rectypes.h b/include/rectypes.h index 4883b8fd8..180e27b40 100755 --- a/include/rectypes.h +++ b/include/rectypes.h @@ -22,7 +22,7 @@ enum TFilelock { enum TReclock { _unlock = 0x1000, // @emem Sblocca il record _nolock = 0x2000, // @emem Nessuna operazione di lock - _lock = 0x4000, // @emem Blocca il record + _lock = 0x4000, // @emem Blocca il record _testandlock = (int)0x8000} ; // @emem Blocca il record se possibile, altrimenti ritorna errore // @doc EXTERNAL @@ -30,7 +30,9 @@ enum TReclock { // @enum TDirtype | Comandi per la gestione di enum TDirtype { _nordir, // @emem Riferimento operazioni col prefix corrente - _comdir } ; // @emem Riferimento operazioni al direttorio comune + _comdir, // @emem Riferimento operazioni al direttorio comune + _studir, // @emem Riferimento operazioni al direttorio studio + _extdir }; // @emem Riferimento operazioni ad un direttorio assoluto // @doc EXTERNAL @@ -94,7 +96,9 @@ enum TIsamerr { _isalropen = 222, // @emem File gia' aperto _isdeadlock = 223, // @emem Condizione di deadlock _isreinsert = 224, // @emem Chiave primaria duplicata - _islocked = 225} ; // @emem Record bloccato + _islocked = 225, // @emem Record bloccato + _isbadtrc = 226 // @emem Tracciato Record errato o mancante +}; typedef long TRecnotype; diff --git a/include/relapp.cpp b/include/relapp.cpp index 045a22228..67d53deec 100755 --- a/include/relapp.cpp +++ b/include/relapp.cpp @@ -1105,7 +1105,7 @@ bool TRelation_application::filter() TAssoc_array field_values; const char * s; - TString80 t; + TString t, v; while((s = body.get()) != NULL) { @@ -1115,7 +1115,7 @@ bool TRelation_application::filter() CHECKS(u > 0, "Invalid edit message ", (const char *) body); if (u > 0) { - const TString v(t.mid(u + 1)); + v = t.mid(u + 1); t.cut(u); field_values.add(t, v); diff --git a/include/relation.cpp b/include/relation.cpp index 17c2e9469..114a301df 100755 --- a/include/relation.cpp +++ b/include/relation.cpp @@ -968,8 +968,10 @@ TRecnotype TCursor::buildcursor(TRecnotype rp) const bool filtered = has_filter(); FILE* _f = open_index(TRUE); + + const int handle = file().handle(); - if (DB_reccount(file().filehnd()->fhnd) == 0) + if (DB_reccount(handle) == 0) { close_index(_f); return 0; @@ -978,19 +980,19 @@ TRecnotype TCursor::buildcursor(TRecnotype rp) rewind(_f); l = strlen(to()); - junk=DB_index_seek(file().filehnd()->fhnd, (char*)(const char*) from()); + junk=DB_index_seek(handle, (char*)(const char*) from()); if (junk < 0) junk=get_error(junk); if (junk == _iseof) return 0; TRecnotype* page = new TRecnotype [CMAXELPAGE]; - pos = DB_index_recno(file().filehnd()->fhnd); + pos = DB_index_recno(handle); _pos=-1; while (TRUE) { - if (DB_index_eof(file().filehnd()->fhnd)) break; - const char* s0 = DB_index_getkey(file().filehnd()->fhnd); - const TRecnotype recno = DB_index_recno(file().filehnd()->fhnd); + if (DB_index_eof(handle)) break; + const char* s0 = DB_index_getkey(handle); + const TRecnotype recno = DB_index_recno(handle); if (l && (strncmp(to(), s0, l) < 0)) break; if (recno == oldrecno) break; // means that no more keys are available oldrecno=recno; @@ -1008,10 +1010,9 @@ TRecnotype TCursor::buildcursor(TRecnotype rp) pagecnt = 0; } page[pagecnt++] = recno; - DB_index_next(file().filehnd()->fhnd); - int rt=get_error(-1); - if (rt != NOERR) - fatal_box("Can't read index n. %d - file n. %d",DB_tagget(file().filehnd()->fhnd),file().filehnd()->ln); + long rec = DB_index_next(handle); + if (rec < 0) + fatal_box("Can't read index n. %d - file n. %d",file().getkey(),file().num()); } // while if (pagecnt) { @@ -1025,7 +1026,7 @@ TRecnotype TCursor::buildcursor(TRecnotype rp) } ap += pagecnt; } - if (_pos == -1) pos=0; + if (_pos == -1) pos = 0; delete page; close_index(_f); return ap; @@ -1033,9 +1034,8 @@ TRecnotype TCursor::buildcursor(TRecnotype rp) int TCursor::filtercursor(int pagecnt, TRecnotype* page) - { - int np=0, handle=file().filehnd()->fhnd; + int np=0; /*, handle = file().handle(); */ TRectype& rec=file().curr(); for (int i=0; i< pagecnt; i++) { @@ -1086,20 +1086,18 @@ bool TCursor::ok() const bool TCursor::changed() { - isdef* fh = file().filehnd(); - if (_frozen && _lastrec > 0L) - return _filename != fh->d->SysName; - - const TRecnotype eod = DB_reccount(fh->fhnd); - if (_lastrec != eod || - (_lastkrec != DB_changed(fh->fhnd)) || - (_filename != fh->d->SysName)) - { - // _lastrec = eod; - // _filename = fh->d->SysName; - // _lastkrec = DB_changed(fh->fhnd); + if (prefix().get_dirtype(file().num()) == _nordir && + _index_firm != prefix().get_codditta()) + return TRUE; + + if (_frozen && _lastrec > 0L) + return FALSE; + + const int handle = file().handle(); + const TRecnotype eod = DB_reccount(handle); + if (_lastrec != eod || + _lastkrec != DB_changed(handle)) return TRUE; - } if (!curr().valid()) return TRUE; @@ -1108,23 +1106,21 @@ bool TCursor::changed() } TRecnotype TCursor::update() - { - begin_wait(); + TWait_cursor hourglass; file().setkey(_nkey); - if (file().curr().empty()) file().curr().zero(); + if (file().curr().empty()) + file().curr().zero(); file().read(_isgteq); const TRecnotype totrec = buildcursor(file().recno()); - isdef* fh = file().filehnd(); - const TRecnotype eod = DB_reccount(fh->fhnd); + const int handle = file().handle(); + const TRecnotype eod = DB_reccount(handle); _lastrec = eod; - _filename = fh->d->SysName; - _lastkrec = DB_changed(fh->fhnd); - - end_wait(); + _index_firm = prefix().get_codditta(); + _lastkrec = DB_changed(handle); return totrec; } @@ -1295,7 +1291,7 @@ TRecnotype TCursor::read(TIsamop op, TReclock lockop) FILE* _f = open_index(); if (fseek(_f, 0L, SEEK_SET) != 0) - fatal_box("Can't repos cursor : File %d\n", file().filehnd()->ln); + fatal_box("Can't repos cursor : File %d\n", curfile.num()); TRecnotype *page = new TRecnotype [CMAXELPAGE]; int pagecnt; @@ -1339,10 +1335,16 @@ TCursor::TCursor(TRelation* r, const char* fil, int nkey, TCursor::~TCursor() - { if (_indexname.not_empty()) + { + if (_indexname == _last_name && _last_ndx != NULL) + { + _last_created = TRUE; // Force close + close_index(_last_ndx); + } ::remove(_indexname); + } if (_fexpr) delete _fexpr; } @@ -1350,23 +1352,23 @@ TCursor::~TCursor() TRecnotype TCursor::readrec() { - TRecnotype& nrec = file().filehnd()->RecNo; + TRecnotype nrec = 0L; if (_pos >= items()) { file().setstatus(_iseof); curr().zero(); - return nrec = 0L; + return nrec; } file().setstatus(NOERR); FILE* _f = open_index(); if (fseek(_f, _pos * sizeof(TRecnotype), SEEK_SET) != 0) - fatal_box("Can't seek position %ld in cursor n. %d\n", _pos, file().filehnd()->ln); + fatal_box("Can't seek position %ld in cursor n. %d\n", _pos, file().num()); if (fread(&nrec, sizeof(TRecnotype), 1, _f) != 1) - fatal_box("Can't read position %ld in cursor n. %d\n", _pos, file().filehnd()->ln); + fatal_box("Can't read position %ld in cursor n. %d\n", _pos, file().num()); close_index(_f); @@ -1389,10 +1391,10 @@ int TCursor::lock( switch(l) { case _lock: - rt=DB_lock_rec(file().filehnd()->fhnd,_pos); + rt=DB_lock_rec(file().handle(),_pos); break; case _unlock: - rt=DB_unlock(file().filehnd()->fhnd); + rt=DB_unlock(file().handle()); break; default: break; @@ -1549,28 +1551,29 @@ TRecnotype TSorted_cursor::buildcursor(TRecnotype rp) FILE* _f = open_index(TRUE); - if (DB_reccount(file().filehnd()->fhnd) == 0) + if (file().empty()) { close_index(_f); return 0; } + const int handle = file().handle(); fseek(_f, 0L, SEEK_SET); l = strlen(to()); - junk=DB_index_seek(file().filehnd()->fhnd, (char*)(const char*) from()); + junk=DB_index_seek(handle, (char*)(const char*) from()); if (junk < 0) junk=get_error(junk); if (junk == _iseof) return 0; TRecnotype* page = new TRecnotype [CMAXELPAGE]; - pos = DB_index_recno(file().filehnd()->fhnd); + pos = DB_index_recno(handle); TCursor::pos()=-1; while (TRUE) { - if (DB_index_eof(file().filehnd()->fhnd)) break; - const char* s0 = DB_index_getkey(file().filehnd()->fhnd); - const TRecnotype recno = DB_index_recno(file().filehnd()->fhnd); + if (DB_index_eof(handle)) break; + const char* s0 = DB_index_getkey(handle); + const TRecnotype recno = DB_index_recno(handle); if (l && (strncmp(to(), s0, l) < 0)) break; if (recno == oldrecno) break; // means that no more keys are available oldrecno=recno; @@ -1587,10 +1590,10 @@ TRecnotype TSorted_cursor::buildcursor(TRecnotype rp) pagecnt = 0; } page[pagecnt++] = recno; // lasciare cosi' altrimenti la readat legge due volte lo stesso record - DB_index_next(file().filehnd()->fhnd); - int rt=get_error(-1); - if (rt != NOERR) - fatal_box("Can't read index n. %d - file n. %d",DB_tagget(file().filehnd()->fhnd),file().filehnd()->ln); + + long rec = DB_index_next(handle); + if (rec < 0) + fatal_box("Can't read index n. %d - file n. %d",file().getkey(),file().num()); } // while if (pagecnt) { @@ -1629,7 +1632,7 @@ TRecnotype TSorted_cursor::buildcursor(TRecnotype rp) int TSorted_cursor::filtercursor(int pagecnt, TRecnotype* page) { - int np=0, handle=file().filehnd()->fhnd; + int np=0 /*, handle=file().filehnd()->fhnd */; TRectype& rec=file().curr(); TString s; El_To_Sort Element; @@ -1657,7 +1660,7 @@ int TSorted_cursor::filtercursor(int pagecnt, TRecnotype* page) s.cut(s.len()-1); TFieldref f(s,0); TString sf=f.read(*relation()); - TRectype& frec = file(f.file()).curr(); + TRectype& frec = file(f.file()).curr(); TFieldtypes fld_type = frec.type(f.name()); if (fld_type == _datefld) // Se il campo e' di tipo data, la converte in ANSI! { diff --git a/include/relation.h b/include/relation.h index b5b560456..d4f841aba 100755 --- a/include/relation.h +++ b/include/relation.h @@ -235,8 +235,8 @@ class TCursor : public TContainer TRecnotype _lastrec; // @cmember:(INTERNAL) Chiave dell'ultimo record TRecnotype _lastkrec; - // @cmember:(INTERNAL) Nome assoluto del file principale - TFilename _filename; + // @cmember:(INTERNAL) Ditta di creazione indice + long _index_firm; // @cmember:(INTERNAL) Filtro definito con la TString _filter; // @cmember:(INTERNAL) Nome della chiave iniziale