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
This commit is contained in:
guy 2009-01-07 15:50:52 +00:00
parent f318b43a1e
commit e2a19d9e23
8 changed files with 290 additions and 328 deletions

View File

@ -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<CB4FILES;i++)
@ -116,23 +114,39 @@ int DB_open(const char *filename,int mode,int index)
break;
}
}
/* se non ci sono posti liberi torna -1 */
if(found==-1)
return(found);
code_base.errorCode=0;
if (index == 0) /* Se e' stata richiesta l'apertura senza indici, setta il flag */
code_base.autoOpen = 0;
dbdata[found]=d4open(&code_base, filename);
if (index == 0) /* Restore the configuration of opening indexes*/
code_base.autoOpen = 1;
if(dbdata[found]==0)
return code_base.errorCode;
code_base.accessMode=0;
d4tagSelect(dbdata[found],d4tagDefault(dbdata[found]));
if (d4recCount(dbdata[found]) > 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<index_no;i++) {
tt=d4tagNext(dbdata[handle],tt);
if(tt==NULL) return(-1);
tt=d4tagNext(data, NULL);
if (tt==NULL)
return -1;
for(i=1; i<index_no; i++)
{
tt=d4tagNext(data, tt);
if(tt==NULL)
return(-1);
}
d4tagSelect(dbdata[handle],tt);
return(0);
d4tagSelect(data, tt);
return 0;
}
@ -226,16 +245,18 @@ int DB_tagget(int handle)
{
TAG4 *tt,*tt1;
int i;
if(!handle_ok(handle)) return(-1);
HANDLE2DATA(handle, data);
/* si posiziona sul primo indice */
tt=d4tagDefault(dbdata[handle]);
if(tt==NULL) return(-1);
tt=d4tagDefault(data);
if(tt==NULL)
return(-1);
tt1=d4tagNext(dbdata[handle],NULL);
tt1=d4tagNext(data,NULL);
i=1;
while(tt!=tt1 && tt1!=NULL) {
tt1=d4tagNext(dbdata[handle],tt1);
while(tt!=tt1 && tt1!=NULL)
{
tt1=d4tagNext(data,tt1);
i++;
}
return(i);
@ -247,8 +268,8 @@ int DB_tagget(int handle)
--------------------------------------------------------------------------*/
int DB_first(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4top(dbdata[handle]));
HANDLE2DATA(handle, data);
return d4top(data);
}
@ -258,8 +279,8 @@ int DB_first(int handle)
--------------------------------------------------------------------------*/
int DB_last(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4bottom(dbdata[handle]));
HANDLE2DATA(handle, data);
return d4bottom(data);
}
@ -268,8 +289,7 @@ int DB_last(int handle)
--------------------------------------------------------------------------*/
int DB_next(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],1L));
return DB_skip(handle, +1);
}
/*-------------------------------------------------------------------------
@ -277,18 +297,16 @@ int DB_next(int handle)
--------------------------------------------------------------------------*/
int DB_prev(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],-1L));
return DB_skip(handle, -1);
}
/*-------------------------------------------------------------------------
skip di n records
--------------------------------------------------------------------------*/
int DB_skip(int handle,long int recno)
int DB_skip(int handle, long recno)
{
if(!handle_ok(handle)) return(-1);
return(d4skip(dbdata[handle],recno));
HANDLE2DATA(handle, data);
return d4skip(data, recno);
}
/*-------------------------------------------------------------------------
@ -296,8 +314,8 @@ int DB_skip(int handle,long int recno)
--------------------------------------------------------------------------*/
int DB_lock(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4lock(dbdata[handle],d4recNo(dbdata[handle])));
HANDLE2DATA(handle, data);
return d4lock(data, d4recNo(data));
}
/*-------------------------------------------------------------------------
@ -305,8 +323,8 @@ int DB_lock(int handle)
--------------------------------------------------------------------------*/
int DB_unlock(int handle)
{
if(!handle_ok(handle)) return(-1);
return(d4unlock(dbdata[handle]));
HANDLE2DATA(handle, data);
return d4unlock(data);
}
/*-------------------------------------------------------------------------
@ -318,12 +336,12 @@ int DB_seek(int handle,char *key)
int rc, len;
const char * k;
if(!handle_ok(handle)) return(-1);
rc = d4seek(dbdata[handle],key);
HANDLE2DATA(handle, data);
rc = d4seek(data,key);
if (rc)
return rc;
len = a4tagKeyLen(dbdata[handle]);
k = a4tagKey(dbdata[handle]);
len = a4tagKeyLen(data);
k = a4tagKey(data);
while (len > 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; ((i<r->NFields) && (i<MaxFields)); i++) /* Construct field_info */
{
field_info[i].name = (char*)u4alloc(16); // In realtà basterebbero 12
strcpy(field_info[i].name,r->Fd[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)

View File

@ -30,54 +30,6 @@
#include <codeb.h>
#include <nditte.h>
#ifdef JOURNAL
#include <journal.h>
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);
}

View File

@ -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);
}

View File

@ -4,6 +4,24 @@
#include <tabutil.h>
#include <user.h>
///////////////////////////////////////////////////////////
// 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

View File

@ -9,8 +9,6 @@
#include <isam.h>
#endif
#include <user.h>
///////////////////////////////////////////////////////////
// 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

View File

@ -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;
}

View File

@ -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 <p m>
@ -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&)

View File

@ -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)