From e2a19d9e237d46b60e17dca8ab3a0bc77aede0ff Mon Sep 17 00:00:00 2001 From: guy Date: Wed, 7 Jan 2009 15:50:52 +0000 Subject: [PATCH] Patch level : 10.0 Files correlati : tutti Ricompilazione Demo : [ ] Commento : Migliorate prestazioni in fase di scrittura su file aperti in modo esclusivo Migliorata gestione dei lock nelle applicazioni di modifica tabelle git-svn-id: svn://10.65.10.50/trunk@17992 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- include/codeb.c | 384 ++++++++++++++++++++++--------------------- include/isam.cpp | 135 ++++----------- include/prefix.cpp | 20 +-- include/recarray.cpp | 36 +++- include/recarray.h | 5 +- include/relapp.cpp | 32 ++-- include/relapp.h | 4 +- include/reputils.cpp | 2 +- 8 files changed, 290 insertions(+), 328 deletions(-) diff --git a/include/codeb.c b/include/codeb.c index 987d60108..85eb2145d 100755 --- a/include/codeb.c +++ b/include/codeb.c @@ -36,13 +36,11 @@ #define MAXLEN 137 /* Lunghezza massima chiave */ static CODE4 code_base; -static DATA4 *dbdata[CB4FILES]; +static DATA4* dbdata[CB4FILES]; +static bool dbfast[CB4FILES]; -static bool handle_ok(int handle) -{ - return handle >= 0 && handle < CB4FILES && - dbdata[handle] != NULL && dbdata[handle]->clientId >= 0; -} +#define HANDLE2DATA(handle, data) DATA4* data = dbdata[handle]; if (handle < 0 || handle >= CB4FILES || data == NULL || data->clientId < 0) return -1 +#define HANDLE2DATASTR(handle, data) DATA4* data = dbdata[handle]; if (handle < 0 || handle >= CB4FILES || data == NULL || data->clientId < 0) return NULL static const char* find_slash_backslash(const char* s) { @@ -77,6 +75,7 @@ void DB_init(void) code_base.lockAttempts=1; code4dateFormatSet(&code_base, "CCYYMMDD"); + code_base.optimize = OPT4EXCLUSIVE; // Is the default? code_base.optimizeWrite = OPT4EXCLUSIVE; // Is the default? } @@ -89,9 +88,9 @@ void DB_init(void) void DB_exit(void) { int i; - for(i=0; i< CB4FILES; i++) + for (i = 0; i < CB4FILES; i++) { - if (handle_ok(i)) + if (dbdata[i] != NULL) DB_close(i); } code4initUndo(&code_base); @@ -101,11 +100,10 @@ void DB_exit(void) apertura del file 'filename'. Il parametro mode consente se != 0 l'apertura esclusiva. Il parametro index consente se == 0 l'apertura senza indici --------------------------------------------------------------------------*/ + int DB_open(const char *filename,int mode,int index) { int i,found; - if (mode) - code_base.accessMode=1; // Exclusive mode /* cerca il primo posto libero nel vettore dbdata */ found=-1; for(i=0;i 0) - d4top(dbdata[found]); - return(found); + if (found >= 0) + { + if (mode) + code_base.accessMode=1; // Exclusive mode + + code_base.errorCode=0; + if (!index) + { + code_base.autoOpen = 0; // Se e' stata richiesta l'apertura senza indici, resetta il flag autoOpen + dbdata[found]=d4open(&code_base, filename); + code_base.autoOpen = 1; + } + else + dbdata[found]=d4open(&code_base, filename); + + if (mode) + code_base.accessMode=0; // Not-Exclusive mode + + if(dbdata[found]!=NULL) + { + HANDLE2DATA(found, data); + + // Guy: Non capisco bene perche' seleziono comunque un indice + d4tagSelect(data, d4tagDefault(data)); + if (d4recCount(data) > 0) + d4top(data); + + dbfast[found] = mode!=0; // Ottimizabile se esclusivo + } + else + return code_base.errorCode; + } + return found; } @@ -142,31 +156,32 @@ int DB_open(const char *filename,int mode,int index) --------------------------------------------------------------------------*/ int DB_close(int handle) { - if(!handle_ok(handle)) return(-1); + HANDLE2DATA(handle, data); - d4close(dbdata[handle]); - dbdata[handle]=(DATA4 *) 0; + d4close(data); + dbdata[handle] = NULL; + dbfast[handle] = FALSE; code_base.errorCode=0; - return(0); + return 0; } /*------------------------------------------------------------------------- torna il puntatore al buffer del record del database individuato da handle. In caso di errore torna (char *) 0 --------------------------------------------------------------------------*/ -char *DB_getrecord(int handle) +char* DB_getrecord(int handle) { - if(!handle_ok(handle)) return((char *) 0); - return(d4record(dbdata[handle])); + HANDLE2DATASTR(handle, data); + return d4record(data); } /*------------------------------------------------------------------------- torna la lunghezza del record --------------------------------------------------------------------------*/ -int DB_reclen(int handle) +int DB_reclen(int handle) { - if(!handle_ok(handle)) return(-1); - return((int) d4recWidth(dbdata[handle])); + HANDLE2DATA(handle, data); + return (int)d4recWidth(data); } /*------------------------------------------------------------------------- @@ -175,7 +190,8 @@ int DB_reclen(int handle) int DB_keylen(int handle) { - return a4tagKeyLen(dbdata[handle]); + HANDLE2DATA(handle, data); + return a4tagKeyLen(data); } /*------------------------------------------------------------------------- @@ -183,8 +199,8 @@ int DB_keylen(int handle) --------------------------------------------------------------------------*/ long int DB_recno(int handle) { - if(!handle_ok(handle)) return(-1L); - return(d4recNo(dbdata[handle])); + HANDLE2DATA(handle, data); + return d4recNo(data); } /*------------------------------------------------------------------------- @@ -192,29 +208,32 @@ long int DB_recno(int handle) --------------------------------------------------------------------------*/ long int DB_reccount(int handle) { - if(!handle_ok(handle)) return(-1L); - return(d4recCount(dbdata[handle])); + HANDLE2DATA(handle, data); + return d4recCount(data); } /*------------------------------------------------------------------------- seleziona un indice sul database specificato torna -1 se errore, altrimenti 0 --------------------------------------------------------------------------*/ -int DB_tagselect(int handle,int index_no) +int DB_tagselect(int handle,int index_no) { TAG4 *tt; int i; - if(!handle_ok(handle)) return(-1); + HANDLE2DATA(handle, data); /* si posiziona sul primo indice */ - tt=d4tagNext(dbdata[handle],NULL); - if(tt==NULL) return(-1); - for(i=1;i 0 && k[len-1] == ' ') len--; rc = strncmp(key, k, len); if (rc == 0) @@ -340,8 +358,8 @@ int DB_seek(int handle,char *key) --------------------------------------------------------------------------*/ int DB_eof(int handle) { - if(!handle_ok(handle)) return(-1); - return(d4eof(dbdata[handle])); + HANDLE2DATA(handle, data); + return d4eof(data); } /*------------------------------------------------------------------------- @@ -349,8 +367,8 @@ int DB_eof(int handle) --------------------------------------------------------------------------*/ int DB_bof(int handle) { - if(!handle_ok(handle)) return(-1); - return(d4bof(dbdata[handle])); + HANDLE2DATA(handle, data); + return d4bof(data); } /*------------------------------------------------------------------------- @@ -358,8 +376,8 @@ int DB_bof(int handle) --------------------------------------------------------------------------*/ int DB_go(int handle,long recno) { - if(!handle_ok(handle)) return(-1); - return(d4go(dbdata[handle],recno)); + HANDLE2DATA(handle, data); + return d4go(data,recno); } /*------------------------------------------------------------------------- @@ -367,10 +385,9 @@ int DB_go(int handle,long recno) --------------------------------------------------------------------------*/ int DB_delete(int handle) { - - if(!handle_ok(handle)) return(-1); - d4delete(dbdata[handle]); - return(0); + HANDLE2DATA(handle, data); + d4delete(data); + return 0; } /*------------------------------------------------------------------------- @@ -378,10 +395,9 @@ int DB_delete(int handle) --------------------------------------------------------------------------*/ int DB_recall(int handle) { - - if(!handle_ok(handle)) return(-1); - d4recall(dbdata[handle]); - return(0); + HANDLE2DATA(handle, data); + d4recall(data); + return 0; } /*------------------------------------------------------------------------- @@ -389,9 +405,19 @@ int DB_recall(int handle) --------------------------------------------------------------------------*/ int DB_flush(int handle) { - int rt; - while ((rt = d4flush(dbdata[handle])) == r4locked) - u4delaySec(); + int rt = 0; + HANDLE2DATA(handle, data); + + if (dbfast[handle]) + { + if (data->dataFile->nFieldsMemo > 0) + rt = d4write(data, -1); + } + else + { + while ((rt = d4flush(data)) == r4locked) + u4delaySec(); + } return rt; } @@ -400,9 +426,9 @@ int DB_flush(int handle) --------------------------------------------------------------------------*/ int DB_rewrite(int handle) { - int rt; - if(!handle_ok(handle)) return(-1); - while ((rt=d4write(dbdata[handle],d4recNo(dbdata[handle]))) == r4locked) + int rt = -1; + HANDLE2DATA(handle, data); + while ((rt=d4write(data,d4recNo(data))) == r4locked) u4delaySec(); if (rt == e4unique) @@ -410,7 +436,7 @@ int DB_rewrite(int handle) char msg[256]; DB_get_error(); sprintf(msg, "Errore in DB_rewrite(): chiave duplicata nel record %ld, file %s", - d4recNo(dbdata[handle]) + 1, d4fileName(dbdata[handle])); + d4recNo(data) + 1, d4fileName(data)); xvt_dm_post_fatal_exit(msg); } @@ -426,13 +452,12 @@ int DB_rewrite(int handle) --------------------------------------------------------------------------*/ int DB_add(int handle) { - int rt; - DATA4 * data = dbdata[handle]; - - if (data==0) return(-1); + int rt = -1; + HANDLE2DATA(handle, data); while ((rt = d4appendStart(data,0)) == r4locked) u4delaySec(); + if (rt == 0) { d4recall(data); @@ -440,8 +465,7 @@ int DB_add(int handle) u4delaySec(); if (rt == e4unique) { - long rec_num = d4recNo(data); - + const long rec_num = d4recNo(data); DB_get_error(); if (rec_num > 0) { @@ -460,7 +484,7 @@ int DB_add(int handle) } } - return(rt); + return rt; } /*------------------------------------------------------------------------- @@ -469,12 +493,10 @@ int DB_add(int handle) int DB_lockfile(int handle) { int rt = -1; - if(handle_ok(handle)) - { - rt = d4lockFile(dbdata[handle]); - if (rt==0) - rt=d4lockIndex(dbdata[handle]); - } + HANDLE2DATA(handle, data); + rt = d4lockFile(data); + if (rt==0) + rt = d4lockIndex(data); return rt; } @@ -808,8 +830,7 @@ int DB_build(const char* filename, const RecDes* r) for (i=0; ((iNFields) && (iFd[i].Name); + field_info[i].name = (char*)r->Fd[i].Name; field_info[i].len = r->Fd[i].Len; field_info[i].dec = r->Fd[i].Dec; switch (r->Fd[i].TypeF) @@ -851,31 +872,14 @@ int DB_build(const char* filename, const RecDes* r) do_key(ff,r,tag_info, MaxKeys); - if ((dbuilded=d4create(&code_base, (char *)filename, field_info, tag_info))==0) /* deve solo creare il file dati vuoto */ + if ((dbuilded=d4create(&code_base, filename, field_info, tag_info))==0) /* deve solo creare il file dati vuoto */ rt=code_base.errorCode; else rt=d4close(dbuilded); - /* Non abbiamo mai usato e speriamo mai useremo questo genere di files!!!! - if (u4switch() & 2 || u4switch() & 8) //Rebuild filename.cgp for CLIPPER AND DBIII only - { - FILE* fp; - char xx[81]; - strcpy(xx,filename); - strcat(xx,".cgp"); - fp=fopen(xx,"w"); - if (fp != NULL) - { - int j; - for (j=0; tag_info[j].name ; j++) - fprintf(fp,"%s\n",tag_info[j].name); - fclose(fp); - } - }*/ if (rt!=0) rt=code_base.errorCode; - for (i=0; ((i < MaxFields) && (i < r->NFields)); i++) - u4free(field_info[i].name); + for (i=0; ((i < MaxKeys) && (i < r->NKeys)); i++) { u4free((char *) tag_info[i].name); @@ -997,13 +1001,14 @@ void DB_zero_error(void) int DB_index_seek(int handle, const char* from) { - TAG4 *t; - - if(!handle_ok(handle)) return(-1); - if ((t=d4tagDefault(dbdata[handle]))==NULL) return(-1); - - if (tfile4seek(t->tagFile,from,strlen(from)) < 0) return(DB_get_error()); - return(0); + TAG4* t = NULL; + HANDLE2DATA(handle, data); + t = d4tagDefault(data); + if (t==NULL) + return -1; + if (tfile4seek(t->tagFile, from, strlen(from)) < 0) + return DB_get_error(); + return 0; } @@ -1014,11 +1019,12 @@ int DB_index_seek(int handle, const char* from) long DB_index_recno(int handle) { TAG4 *t; + HANDLE2DATA(handle, data); + t=d4tagDefault(data); + if (t==NULL) + return(-1); - if(!handle_ok(handle)) return(-1); - if ((t=d4tagDefault(dbdata[handle]))==NULL) return(-1); - - return(tfile4recNo(t->tagFile)); + return tfile4recNo(t->tagFile); } /*------------------------------------------------------------------------- @@ -1027,11 +1033,11 @@ long DB_index_recno(int handle) long DB_index_next(int handle) { TAG4 *t; - - if(!handle_ok(handle)) return(-1); - if ((t=d4tagDefault(dbdata[handle]))==NULL) return(-1); - - return(tfile4skip(t->tagFile,1L)); + HANDLE2DATA(handle, data); + t = d4tagDefault(data); + if (t==NULL) + return -1; + return tfile4skip(t->tagFile,1L); } /*------------------------------------------------------------------------- @@ -1040,18 +1046,17 @@ long DB_index_next(int handle) char* DB_index_getkey(int handle) { - static char* key = NULL; + static char key[MAXLEN]; TAG4 *t; int klen; + + HANDLE2DATASTR(handle, data); - if (key == NULL) - key = malloc(MAXLEN); - if(!handle_ok(handle)) + if ((t=d4tagDefault(data))==NULL) return(NULL); - if ((t=d4tagDefault(dbdata[handle]))==NULL) return(NULL); - klen=a4tagKeyLen(dbdata[handle]); + klen=a4tagKeyLen(data); if (klen > (MAXLEN-1)) klen=MAXLEN-1; - memcpy(key,a4tagKey(dbdata[handle]),klen); /* tfile4key non restituisce una null terminated string */ + memcpy(key,a4tagKey(data),klen); /* tfile4key non restituisce una null terminated string */ key[klen]='\0'; return key; } @@ -1061,12 +1066,12 @@ char* DB_index_getkey(int handle) --------------------------------------------------------------------------*/ int DB_index_go(int handle, const char* key, long recno) { - TAG4 *t; - - if(!handle_ok(handle)) return(-1); - if ((t=d4tagDefault(dbdata[handle]))==NULL) return(-1); - - return(tfile4go(t->tagFile, key, recno, FALSE)); + TAG4* t = NULL; + HANDLE2DATA(handle, data); + t = d4tagDefault(data); + if (t==NULL) + return -1; + return tfile4go(t->tagFile, key, recno, FALSE); } /*------------------------------------------------------------------------- @@ -1075,22 +1080,22 @@ int DB_index_go(int handle, const char* key, long recno) int DB_index_eof(int handle) { - TAG4 *t; - - if(!handle_ok(handle)) return(-1); - if ((t=d4tagDefault(dbdata[handle]))==NULL) return(-1); - return(tfile4eof(t->tagFile)); + TAG4* t = NULL; + HANDLE2DATA(handle, data); + t = d4tagDefault(data); + if (t==NULL) + return -1; + return tfile4eof(t->tagFile); } /*------------------------------------------------------------------------- Blocca il record indicato --------------------------------------------------------------------------*/ -int DB_lock_rec(int handle,long nrec) +int DB_lock_rec(int handle, long nrec) { - if(!handle_ok(handle)) return(-1); - if(d4lock(dbdata[handle],nrec)==r4locked) return(-1); - else return(0); + HANDLE2DATA(handle, data); + return d4lock(data, nrec)==r4locked ? -1 : 0; } /*------------------------------------------------------------------------- @@ -1098,11 +1103,10 @@ int DB_lock_rec(int handle,long nrec) in modo esclusivo dalla presente applicazione, non da altri programmi!!! --------------------------------------------------------------------------*/ - int DB_file_locked(int handle) { - if(!handle_ok(handle)) return(-1); - return a4lockTest(dbdata[handle]); + HANDLE2DATA(handle, data); + return a4lockTest(data); } /*------------------------------------------------------------------------- @@ -1110,10 +1114,10 @@ int DB_file_locked(int handle) non da altri programmi!!! --------------------------------------------------------------------------*/ -int DB_rec_locked(int handle,long nrec) +int DB_rec_locked(int handle, long nrec) { - if(!handle_ok(handle)) return(-1); - return(d4lockTest(dbdata[handle],nrec)); + HANDLE2DATA(handle, data); + return d4lockTest(data,nrec); } /*------------------------------------------------------------------------- @@ -1122,7 +1126,7 @@ int DB_rec_locked(int handle,long nrec) long DB_getconf() { - return(u4switch()); + return u4switch(); } /*------------------------------------------------------------------------- @@ -1131,26 +1135,24 @@ long DB_getconf() long DB_changed(int handle) { - return(a4indexVersion(dbdata[handle])); + HANDLE2DATA(handle, data); + return a4indexVersion(data); } char* DB_memoptr( const int handle, const char * fieldname ) { - FIELD4* f = d4field( dbdata[ handle ], fieldname ); - return f4memoPtr( f ); + FIELD4* f = NULL; + HANDLE2DATASTR(handle, data); + f = d4field(data, fieldname); + return f4memoPtr(f); } -int DB_memowrite( const int handle, const char* fieldname, const char* data ) +int DB_memowrite( const int handle, const char* fieldname, const char* memo ) { - FIELD4* f = d4field(dbdata[handle], fieldname ); - int ret = f4memoAssign( f, data ); - - if (ret == 0) - { - d4flush(dbdata[handle]); - d4unlock(dbdata[handle]); - } - return ret; + FIELD4* f = NULL; + HANDLE2DATA(handle, data); + f = d4field(data, fieldname); + return f4memoAssign(f, memo); } long DB_version(char* str, int maxstr) diff --git a/include/isam.cpp b/include/isam.cpp index 94e887d56..61b2921ae 100755 --- a/include/isam.cpp +++ b/include/isam.cpp @@ -30,54 +30,6 @@ #include #include -#ifdef JOURNAL -#include - -static FILE* _journal = (FILE*)0xFFFF; - -FILE* get_journal() -{ - if (_journal == (FILE*)0xFFFF) - { - TConfig ini(CONFIG_INSTALL, "Main"); - const TString& name = ini.get("Journal"); - if (name.not_empty()) - _journal = fopen(name, "ab"); - else - _journal = NULL; - } - return _journal; -} - -TJournalHeader& get_journal_header(int num, const char* op, const char* type) -{ - static TJournalHeader jh; - const int size = sizeof(TJournalHeader); - CHECKD(size == 64, "Invalid journal header: ", size); - - memset(&jh, 0, size); - strcpy(jh._signature, "J00"); - jh._header_length = size; - time(&jh._time); - jh._firm = prefix().get_codditta(); - jh._logic_num = num; - strcpy(jh._operation, op); - strcpy(jh._type, type); - jh._data_size = 0; - return jh; -} - -void write_journal(TJournalHeader& jh, void* data, int len) -{ - FILE* j = get_journal(); - jh._data_size = len; - fwrite(&jh, sizeof(TJournalHeader), 1, j); - fwrite(data, len, 1, j); - fflush(j); -} - -#endif - #define RECLOCKTYPES 0xFF00 #define READTYPES 0x00FF #define INVFLD 255 @@ -1048,17 +1000,7 @@ int TBaseisamfile::_write(const TRectype& rec) memcpy(DB_getrecord(fhnd), rec.string(), dst_len); _lasterr = DB_add(fhnd); - if (_lasterr == NOERR) - { -#ifdef JOURNAL - if (get_journal()) - { - TJournalHeader& jh = get_journal_header(num(), "ADD", "REC"); - write_journal(jh, rec.string(), dst_len); - } -#endif - } - else + if (_lasterr != NOERR) _lasterr = get_error(_lasterr); _recno = DB_recno(fhnd); @@ -1121,16 +1063,7 @@ int TBaseisamfile::_rewrite(const TRectype& rec) memcpy(DB_getrecord(fhnd), rec.string(), len); _lasterr = DB_rewrite(fhnd); if (_lasterr == NOERR) - { -#ifdef JOURNAL - if (get_journal()) - { - TJournalHeader& jh = get_journal_header(num(), "MOD", "REC"); - write_journal(jh, rec.string(), len); - } -#endif rec_cache(_logicnum).notify_change(); - } else _lasterr = get_error(_lasterr); } @@ -1194,8 +1127,7 @@ int TBaseisamfile::_remove(const TRectype& rec) CHECK(!rec.empty(), "Can't remove an empty record"); TRectype save_rec(rec); - // Forza l'uso della chiave principale (per chiavi duplicate?) - const int fhnd = handle(1); + const int fhnd = handle(1); // Forza l'uso della chiave principale (per chiavi duplicate?) _lasterr = cisread(fhnd, 1, save_rec, _isequal + _nolock, _recno); // Si Posiziona per sicurezza... if (_lasterr == NOERR) @@ -1204,14 +1136,6 @@ int TBaseisamfile::_remove(const TRectype& rec) if (_lasterr == NOERR) { DB_flush(fhnd); -#ifdef JOURNAL - if (get_journal()) - { - const int len = DB_reclen(fhnd); - TJournalHeader& jh = get_journal_header(num(), "DEL", "REC"); - write_journal(jh, rec.string(), len); - } -#endif } else { @@ -1220,7 +1144,7 @@ int TBaseisamfile::_remove(const TRectype& rec) } } - if(_lasterr == NOERR) + if (_lasterr == NOERR) { if (curr().has_memo( )) curr().init_memo(); @@ -2107,19 +2031,20 @@ int TSystemisamfile::update( if (dir.eod() > 0 && oldrec.len() > 0) { - err = _open_ex(_excllock, FALSE); - if (err != NOERR) - return err; - // Apro il file destinazione in modo esclusivo e senza indici - int tmpnum = num(); - TIsam_handle ishandle = prefix().open_isamfile(tmpnum, tmpfname, TRUE, FALSE); - TCodeb_handle fhnd = ishandle > 0 ? prefix().get_handle(ishandle) : ishandle; - if (fhnd < 0 ) + //int tmpnum = num(); + //TIsam_handle ishandle = prefix().open_isamfile(tmpnum, tmpfname, true, false); + // TCodeb_handle fhnd = ishandle > 0 ? prefix().get_handle(ishandle) : ishandle; + TCodeb_handle fhnd = DB_open(tmpfname, 1, 0); + if (fhnd < 0) { - err=get_error(fhnd); + err = get_error(fhnd); return err; } + + err = _open_ex(_excllock, false); + if (err != NOERR) + return err; TString s(256); s << TR("Aggiornamento") << ' ' << fname; @@ -2180,14 +2105,29 @@ int TSystemisamfile::update( memcpy(DB_getrecord(fhnd),nrec.string(),lenr); err=DB_add(fhnd); if ( err == NOERR && memo_inside) - nrec.write_memo(ishandle, DB_recno(fhnd)); + { + // nrec.write_memo(ishandle, DB_recno(fhnd)); + for (j = outfld.last(); j >= 0; j = outfld.pred(j)) + { + const TRecfield* in_fld = (const TRecfield*)infld.objptr(j); + const TRecfield* out_fld = (const TRecfield*)outfld.objptr(j); + if (in_fld != NULL && out_fld != NULL && out_fld->type() == _memofld) + { + const TFixed_string val(*in_fld); + if (val.full()) + DB_memowrite(fhnd, out_fld->name(), val); + } + } + DB_flush(fhnd); + } if (err != NOERR) err=get_error(err); setstatus(err); } close(); - prefix().close_isamfile(ishandle); + //prefix().close_isamfile(ishandle); + DB_close(fhnd); if (err != NOERR) err = get_error(err); @@ -3262,30 +3202,24 @@ void TRectype::init(int logicnum) else setempty(TRUE); - const bool has_memo_fld = _length > 0 && lf_has_memo(_logicnum); - - if(has_memo_fld) + if (_length > 0 && lf_has_memo(logicnum)) init_memo(RECORD_NON_FISICO); } TRectype::TRectype(int logicnum) : _memo_data(NULL) - { init(logicnum); } - TRectype::TRectype(const TBaseisamfile* i) : _memo_data(NULL) { init(i->num()); } - TRectype::TRectype(const TRectype& r) - : - _memo_data(NULL) + : _memo_data(NULL) { init(r._logicnum); @@ -3342,11 +3276,12 @@ void TRectype::write_memo(TIsam_handle file, const TRecnotype recno) CHECKD(recno >= 0, "Maiale! Non fare le GO con _recno < 0: ", recno); const TCodeb_handle cb_handle = prefix().get_handle(file); DB_go( cb_handle, recno); - for( int i = _memo_data->last( ); i > 0; i = _memo_data->pred( i ) ) + FOR_EACH_ARRAY_ROW_BACK((*_memo_data), i, memo) { if (_memo_data->is_dirty(i)) - DB_memowrite( cb_handle, r.Fd[ i ].Name, _memo_data->row( i ) ); + DB_memowrite(cb_handle, r.Fd[i].Name, *memo); } + DB_flush(cb_handle); *this = (const char*)DB_getrecord(cb_handle); init_memo(recno, file); } diff --git a/include/prefix.cpp b/include/prefix.cpp index 59ab2ab40..d1b87ab91 100755 --- a/include/prefix.cpp +++ b/include/prefix.cpp @@ -392,7 +392,7 @@ int TFile_info::close_low() DB_close(_handle); _handle = -1; _last_key = -1; - _exclusive = _locked = FALSE; + _exclusive = _locked = false; } else { @@ -412,12 +412,12 @@ int TFile_info::open(bool exclusive, bool index) if (_ref_count > 0 || is_open()) { #ifdef DBG - if (_ref_count > 0) + if (_ref_count > 0 && (_exclusive || _locked)) error_box("You shouldn't reopen file %d exclusively", num()); #endif close_low(); } - _exclusive = _locked = TRUE; + _exclusive = _locked = true; // shouldn't be exclusive instead of true? err = open_low(exclusive, index); } touch(); // Memorizza ora apertura del file @@ -431,7 +431,7 @@ int TFile_info::close() if (_ref_count > 0) { _ref_count--; - if (_ref_count == 0) + if (_ref_count == 0 || _exclusive) { if (is_open()) { @@ -477,10 +477,10 @@ int TFile_info::auto_open(int key) } void TFile_info::lock_record(TRecnotype) -{ _locked = TRUE; } +{ _locked = true; } void TFile_info::unlock_record(TRecnotype) -{ _locked = FALSE; } +{ _locked = false; } const TFilename& TFile_info::load_filedes() { @@ -488,10 +488,7 @@ const TFilename& TFile_info::load_filedes() CGetFile(num(), &_filedes, _nolock, _nordir); if (_filedes.SysName[0] > ' ') { - if (_filedes.SysName[0] != '$') - _dir = _comdir; - else - _dir = _nordir; + _dir = _filedes.SysName[0] != '$' ? _comdir : _nordir; _name = CAddPref(_filedes.SysName); strncpy(_filedes.Des, dictionary_translate(_filedes.Des), sizeof(_filedes.Des)-1); } @@ -665,7 +662,7 @@ TIsam_handle TFile_manager::get_handle(TFilename& name) TIsam_handle TFile_manager::open(int& logicnum, TFilename& name, bool exclusive, bool index) { TIsam_handle num = logicnum; - if (name.not_empty()) + if (name.full()) { num = get_handle(name); if (logicnum >= LF_EXTERNAL) @@ -768,7 +765,6 @@ const RecDes& TFile_manager::get_recdes(int logicnum) const TToken_string& TFile_manager::get_relation(int fromlogic, int tologic) const { TRecord_info& i = recinfo(fromlogic); - return i.relation(tologic); } diff --git a/include/recarray.cpp b/include/recarray.cpp index baba22edc..3f37e8b51 100755 --- a/include/recarray.cpp +++ b/include/recarray.cpp @@ -4,6 +4,24 @@ #include #include +/////////////////////////////////////////////////////////// +// TFast_isamfile +/////////////////////////////////////////////////////////// + +class TFast_isamfile : public TIsamfile +{ +public: + TFast_isamfile(int logicnum); + ~TFast_isamfile() { close(); } +}; + +TFast_isamfile::TFast_isamfile(int logicnum) : TIsamfile(logicnum) +{ + int err = open(_excllock); + if (err != NOERR) + err = open(_manulock); +} + /////////////////////////////////////////////////////////// // TRecord_Array /////////////////////////////////////////////////////////// @@ -329,14 +347,13 @@ int TRecord_array::read(const TRectype& filter) return read(f); } -int TRecord_array::remove_from(int pos) const +int TRecord_array::remove_from(TIsamfile& f, int pos) const { int err = NOERR; TRectype* rec = (TRectype*)key().dup(); CHECK(!rec->empty(), "Can't use empty key"); - TLocalisamfile f(_file); rec->put(_num, pos); for (int e = rec->read(f, _isgteq); e == NOERR && good(*rec); e = rec->next(f)) { @@ -356,6 +373,11 @@ int TRecord_array::remove_from(int pos) const return err; } +int TRecord_array::remove_from(int pos) const +{ + TFast_isamfile f(_file); + return remove_from(f, pos); +} int TRecord_array::write(bool re) const { @@ -363,10 +385,10 @@ int TRecord_array::write(bool re) const int last_on_file = 0; // Last record found on file int err = NOERR; - TLocalisamfile f(_file); + TFast_isamfile f(_file); + const int u = _data.last(); - //TRectype* rec = (TRectype*)key().dup(); CHECK(u<1 || !key().empty(), "Can't write rows using an empty key"); int i; for (i = 1; i <= u; i++) @@ -430,9 +452,9 @@ int TRecord_array::write(bool re) const // Cancella eventuali residui successivi if (err == NOERR && last_on_file != EOR) - remove_from(i + _offset); - - return err; + remove_from(f, i + _offset); + + return err; } int TRecord_array::remove() const diff --git a/include/recarray.h b/include/recarray.h index e05d1d990..8ed3a95b8 100755 --- a/include/recarray.h +++ b/include/recarray.h @@ -9,8 +9,6 @@ #include #endif -#include - /////////////////////////////////////////////////////////// // TRecord_Array /////////////////////////////////////////////////////////// @@ -48,6 +46,9 @@ protected: bool good(const TRectype& rec) const; // @cmember Duplica un record array virtual TObject* dup() const { return new TRecord_array(*this);} + + int remove_from(TIsamfile& f, int pos) const; + // @access Public Member public: // @cmember Ritorna il record che fa da chiave per tutti gli altri diff --git a/include/relapp.cpp b/include/relapp.cpp index 5aa7b73fe..93ca2fbac 100755 --- a/include/relapp.cpp +++ b/include/relapp.cpp @@ -960,6 +960,15 @@ bool TRelation_application::find(word k) return err == NOERR; } +void TRelation_application::edit_cancel() +{ + if (_mask->mode() == MODE_MOD) + { + TRelation* rel = get_relation(); + rel->restore_status(); + rel->lfile().reread(_unlock); // Unlock main file + } +} bool TRelation_application::save(bool check_dirty) { @@ -967,7 +976,10 @@ bool TRelation_application::save(bool check_dirty) int pos = _mask->id2pos(DLG_SAVEREC); if (pos < 0 || !_mask->fld(pos).active()) - return TRUE; + { + edit_cancel(); + return true; + } int err = NOERR; const int mode = _mask->mode(); @@ -983,12 +995,8 @@ bool TRelation_application::save(bool check_dirty) if (!dirty && !was_dirty) { - if (mode == MODE_MOD) - { - get_relation()->restore_status(); - get_relation()->lfile().reread(_unlock); // Unlock main file - } - return TRUE; + edit_cancel(); + return true; } const KEY last = _mask->last_key(); @@ -1035,13 +1043,9 @@ bool TRelation_application::save(bool check_dirty) k = yesnocancel_box(TR("Si desidera registrare?")); if (k == K_ESC || k == K_NO) - { - if (mode == MODE_MOD) - { - get_relation()->restore_status(); - get_relation()->lfile().reread(_unlock); // Unlock main file - } - was_dirty = FALSE; + { + edit_cancel(); + was_dirty = false; return k == K_NO; } diff --git a/include/relapp.h b/include/relapp.h index 816ee315d..26ddaa626 100755 --- a/include/relapp.h +++ b/include/relapp.h @@ -170,6 +170,8 @@ protected: // @cmember Richiede la maschera da usare virtual TMask* get_mask(int mode) pure; + // @cmember:(INTERNAL) Annulla la modifica di un record: toglie il lock + void edit_cancel(); // @cmember:(INTERNAL) Salva i contenuti della maschera su file virtual bool save(bool check_dirty); // @cmember Legge dalla relazione i valori nella maschera

@@ -189,7 +191,7 @@ protected: virtual const char* get_next_key() { return ""; } virtual bool get_next_key(TToken_string& key) - { return FALSE; } + { return false; } // @cmember Richiede se il record corrente e' protetto (non cancellabile) virtual bool protected_record(TRectype&) diff --git a/include/reputils.cpp b/include/reputils.cpp index 0e491bc14..8535b0e33 100755 --- a/include/reputils.cpp +++ b/include/reputils.cpp @@ -158,7 +158,7 @@ bool TLog_report::log(int sev, const char* msg) return ok; } -TLog_report::TLog_report(const char* title, const char* name) +TLog_report::TLog_report(const char* title, const char* name) : _kill_duplicates(false) { load(name); if (recordset() == NULL)