1690 lines
42 KiB
C
Executable File
1690 lines
42 KiB
C
Executable File
/*
|
|
*
|
|
@(SH) Funzioni per la gestione dei file ISAM
|
|
@(C$) PRIVATE
|
|
logname : nome del file di LOG (GIORNALE)
|
|
INTTLOCK : costante che indica alla funzione di lettura che e' stata chaimata dalla funzione di scrittura e quindi deve solo controllare lo stato di lock del record
|
|
ISLOCKED : costante che indica che il record e' bloccato
|
|
@(VG$) PRIVATE
|
|
KSv, PosSv : variabili di lavoro
|
|
PagSv, IndSv : variabili di lavoro
|
|
IndActive : stato indici - TRUE = Aggiornati ad ogni modifica, FALSE = aggiorna solo i dati
|
|
isstate : Stato transazione corrente
|
|
win,wisfd : variabili di lavoro
|
|
isjournal : TRUE scrive il giornale
|
|
openf : array di TUTTI i puntatori ai descrittori dei file ISAM aperti
|
|
-------------------------------------------------------------------------------
|
|
*/
|
|
#include "cisam.h"
|
|
#include "libdefs.h"
|
|
#include "checks.h"
|
|
#include <memory.h>
|
|
#define logname "log.gen"
|
|
#define INTTLOCK 0xF000
|
|
#define ISLOCKED 225
|
|
#define NOALLOC (char **) -1
|
|
TKey KSv;
|
|
int PosSv;
|
|
RecNoType PagSv,IndSv;
|
|
BOOLEAN IndActive = TRUE;
|
|
int isstate = NOTRANS ;
|
|
int wln = -1;
|
|
isfdptr wisfd;
|
|
extern BOOLEAN isjournal;
|
|
/* Guy moved them here from extcdecl.h */
|
|
Str80 cprefix;
|
|
isfdptr* openf;
|
|
void savekeystat(isdef *);
|
|
void restkeystat(isdef *,int );
|
|
int addkeys(isdef *,RecType ,int ,int *);
|
|
int delkeys(isdef *,RecType ,int ,int *);
|
|
int replkeys(isdef *,RecType ,RecType ,int ,int *);
|
|
#ifndef DOS
|
|
void writeundo(int ,isdef *,RecType);
|
|
void writelog(int ,isdef *,RecType);
|
|
char *undoname(void);
|
|
void getopenf(int ,RecType *);
|
|
#endif
|
|
/*
|
|
@($) savekeystat ISAM
|
|
@(ID)
|
|
Salva la chiave corrente.
|
|
@(FD)
|
|
*/
|
|
void savekeystat(isfd)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
{
|
|
strcpy(KSv,isfd->i.Key);
|
|
IndSv = isfd->i.Ind;
|
|
PosSv = isfd->i.Pos;
|
|
PagSv = isfd->i.CurPag;
|
|
}
|
|
/*
|
|
@($) restkeystat ISAM
|
|
@(ID)
|
|
Ripristina la chiave corrente.
|
|
@(FD)
|
|
*/
|
|
void restkeystat(isfd,knum)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
int knum; /* numero della chiave */
|
|
{
|
|
isfd->i.PN = knum - 1;
|
|
strcpy(isfd->i.Key,KSv);
|
|
isfd->i.Ind = IndSv;
|
|
isfd->i.Pos = PosSv;
|
|
isfd->i.CurPag = PagSv;
|
|
}
|
|
/*
|
|
@($) relisfd ISAM
|
|
@(ID)
|
|
Vuota il descrittore del file .
|
|
@(FD)
|
|
*/
|
|
void relisfd(isfd)
|
|
isfdptr *isfd; /* descrittore del file ISAM */
|
|
{
|
|
free((char *) (*isfd)->d);
|
|
free((char *) (*isfd)->r);
|
|
free((char *) (*isfd));
|
|
}
|
|
/*
|
|
@($) getisfd ISAM
|
|
@(ID)
|
|
Alloca e carica il descrittore del file con numero logico "logicname".
|
|
@(FD)
|
|
*/
|
|
void getisfd(isfd, logicname)
|
|
isdef **isfd; /* descrittore del file ISAM */
|
|
int logicname; /* numero logico del file */
|
|
{
|
|
(*isfd) = (isfdptr) malloc(sizeof(**isfd));
|
|
(*isfd)->d = (FileDes *) malloc(sizeof(*((*isfd)->d)));
|
|
(*isfd)->r = (RecDes *) malloc(sizeof(*((*isfd)->r)));
|
|
COpenDir(ManuLock, NORDIR);
|
|
CGetFile(logicname, (*isfd)->d, NoLock, NORDIR);
|
|
if ((!(STREMPTY((*isfd)->d->SysName))) && ((*isfd)->d->SysName[0] == '%'))
|
|
(*isfd)->ft = COMDIR;
|
|
else
|
|
(*isfd)->ft = NORDIR;
|
|
CCloseDir(NORDIR);
|
|
COpenDir(ManuLock, (*isfd)->ft);
|
|
COpenFile(logicname, (*isfd)->d, NoLock, (*isfd)->ft);
|
|
CCloseDir((*isfd)->ft);
|
|
COpenRecDir(ManuLock, (*isfd)->ft);
|
|
CGetRec(logicname,(*isfd)->r, (*isfd)->ft);
|
|
CCloseRecDir((*isfd)->ft);
|
|
}
|
|
/*void dump(s,l)
|
|
RecType s;
|
|
int l;
|
|
{
|
|
message_box("dump : record: %s ", &s[1]);
|
|
}*/
|
|
/*
|
|
@(#) cisupdflags ISAM
|
|
@(ID)
|
|
Aggiorna all'interno del direttorio i campi EOD e Flags.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
@(ISV)
|
|
wd = riga relativa al file ISAM in oggetto nel Direttorio.
|
|
fdir = identificatore del file direttorio.
|
|
- Versione DOS e XENIX
|
|
@(FSV)
|
|
@(IN)
|
|
Il campo Flags viene aggiornato comunque, mentre EOD viene aggiornato solo
|
|
se il parametro di input "updateeod" e' TRUE.
|
|
@(FN)
|
|
*/
|
|
int cisupdflags(isfd,err,updateeod)
|
|
isdef *isfd; /* puntatore al descrittore del file ISAM */
|
|
int *err; /* codice di errore */
|
|
BOOLEAN updateeod; /* se TRUE si aggiorna anche EOD */
|
|
|
|
{
|
|
FileDes wd;
|
|
|
|
*err = NoErr ;
|
|
if (isfd->ln <= 0) return(*err) ;
|
|
COpenDir( ManuLock, isfd->ft);
|
|
COpenFile(isfd->ln, &wd, Lock, isfd->ft);
|
|
if ((*err = fdir[isfd->ft].IOR) == NoErr)
|
|
{
|
|
wd.Flags = isfd->d->Flags;
|
|
/* #ifdef DOS
|
|
if (updateeod) wd.EOD = isfd->d->EOD;
|
|
#else */
|
|
if ((updateeod) && (isfd->f.LockMode == ExclLock)) wd.EOD = isfd->d->EOD;
|
|
/* #endif */
|
|
CCloseFile(isfd->ln, &wd, isfd->ft);
|
|
}
|
|
CCloseDir(isfd->ft);
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisgeteod ISAM
|
|
|
|
@(ID)
|
|
Ritorna l' EOD del file.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
|
|
- Versione DOS e XENIX
|
|
@(FSV)
|
|
|
|
*/
|
|
|
|
RecNoType cisgeteod(isfd,err)
|
|
isfdptr isfd; /* puntatore al descrittore del file ISAM */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
|
|
*err = NoErr ;
|
|
if (isfd->ln > 0)
|
|
{
|
|
COpenDir( ManuLock , isfd->ft);
|
|
COpenFile(isfd->ln, isfd->d, NoLock, isfd->ft);
|
|
CCloseDir(isfd->ft);
|
|
}
|
|
return(isfd->d->EOD) ;
|
|
}
|
|
|
|
/*
|
|
@(#) cisopen ISAM
|
|
|
|
@(ID)
|
|
Apre un file ISAM e alloca il buffer per un record a attiva la chiave 1 (uno).
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
werr = variabile di lavoro che raccoglie il codice errore proveniente dalla CBCloseFile.
|
|
|
|
s = stringa di lavoro per messaggi di errore.
|
|
|
|
- Versione DOS e XENIX
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
@(FN)
|
|
*/
|
|
|
|
int cisopen (isfd,logicname,record,mode,err)
|
|
isfdptr *isfd; /* puntatore al descrittore del file */
|
|
int logicname; /* numero logico */
|
|
RecType *record; /* buffer per contenere un record */
|
|
unsigned int mode; /* modo di apertura (lock) */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
*err = NoErr;
|
|
if (openf[logicname - 1] != NULL)
|
|
fatal_box("File n. %d already open", logicname);
|
|
#ifndef DOS
|
|
if ((excllock(CInsPref(glockname, NORDIR), FALSE) == -1) && (errno == EACCES))
|
|
fatal_box("Can't open directory : Error n. %d ", errno);
|
|
#endif
|
|
getisfd (isfd,logicname);
|
|
COpen(&((*isfd)->f), (*isfd)->d->SysName, (*isfd)->d->LenR, 0, mode);
|
|
if (*err = (*isfd)->f.IOR)
|
|
{
|
|
Str80 name; strcpy(name, (*isfd)->d->SysName);
|
|
relisfd(isfd);
|
|
fatal_box("Can't open file n. %d (%s): error %d ",
|
|
logicname, name, *err);
|
|
}
|
|
if ((*isfd)->r->NKeys)
|
|
{
|
|
Str80 name; strcpy(name, CGetIdxName((*isfd)->d->SysName));
|
|
CBOpenFile (&((*isfd)->i), name, mode, err);
|
|
if (*err)
|
|
{
|
|
CClose(&((*isfd)->f));
|
|
relisfd(isfd);
|
|
fatal_box("Can't open file n. %d (%s): error %d ",
|
|
logicname, name, *err);
|
|
}
|
|
#ifndef DOS
|
|
else
|
|
if (mode == ExclLock)
|
|
{
|
|
CBLockFile(&((*isfd)->i), err);
|
|
if (*err)
|
|
{
|
|
int werr;
|
|
CClose(&((*isfd)->f));
|
|
CBCloseFile(&((*isfd)->i), &werr);
|
|
relisfd(isfd);
|
|
fatal_box("Can't open exclusively file n. %d: error %d ", logicname, *err);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
if (record != NOALLOC)
|
|
*record = (RecType) malloc((*isfd)->d->LenR);
|
|
(*isfd)->ln = logicname;
|
|
openf[logicname - 1] = *isfd;
|
|
if ((*isfd)->r->NKeys) (*isfd)->i.PN = 0;
|
|
return (*err);
|
|
}
|
|
|
|
/*
|
|
@(#) ciscopyrec ISAM
|
|
|
|
@(ID)
|
|
Copia un record dati da un record ad un altro.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
d = riga del direttorio corrispondente al file in esame.
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
@(FN)
|
|
*/
|
|
|
|
int ciscopyrec(logicname,recdest, recsrc ,err)
|
|
int logicname; /* numero logico del file ISAM */
|
|
RecType recdest; /* buffer destinazione */
|
|
RecType recsrc; /* buffer sorgente */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
FileDes d;
|
|
int ft;
|
|
|
|
*err = NoErr;
|
|
if (logicname < 0) logicname = -logicname;
|
|
if (openf[logicname - 1] != NULL) d = *(openf[logicname - 1]->d);
|
|
{
|
|
COpenDir(ManuLock, NORDIR);
|
|
CGetFile(logicname, &d, NoLock, NORDIR);
|
|
if ((!(STREMPTY(d.SysName))) && (d.SysName[0] == '%')) ft = COMDIR;
|
|
else ft = NORDIR;
|
|
CCloseDir(NORDIR);
|
|
COpenDir(ManuLock, ft);
|
|
COpenFile(logicname, &d, NoLock, ft);
|
|
CCloseDir(ft);
|
|
}
|
|
memcpy(recdest, recsrc, d.LenR);
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisallocrec ISAM
|
|
|
|
@(ID)
|
|
Alloca il buffer per un record.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
d = riga del direttorio corrispondente al file in esame.
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
@(FN)
|
|
*/
|
|
|
|
int cisallocrec(logicname,record,err)
|
|
int logicname; /* numero logico del file ISAM */
|
|
RecType *record; /* buffer per il record */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
FileDes d;
|
|
int ft;
|
|
|
|
*err = NoErr;
|
|
if (logicname < 0) logicname = -logicname;
|
|
if (openf[logicname - 1] != NULL) d = *(openf[logicname - 1]->d);
|
|
else
|
|
{
|
|
COpenDir(ManuLock, NORDIR);
|
|
CGetFile(logicname, &d, NoLock, NORDIR);
|
|
if ((!(STREMPTY(d.SysName))) && (d.SysName[0] == '%')) ft = COMDIR;
|
|
else ft = NORDIR;
|
|
CCloseDir(NORDIR);
|
|
COpenDir(ManuLock, ft);
|
|
COpenFile(logicname, &d, NoLock, ft);
|
|
CCloseDir(ft);
|
|
}
|
|
*record = (RecType) malloc(d.LenR);
|
|
if (*record == ((RecType) NULL)) return(ENOMEM);
|
|
else return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisclose ISAM
|
|
|
|
@(ID)
|
|
Chiude un file ISAM e libera il buffer del record.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
werr = variabile di lavoro che raccoglie il codice errore proveniente dalla CBCloseFile.
|
|
|
|
s[20] = stringa di lavoro per messaggi di errore.
|
|
|
|
- Versione DOS e XENIX
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
Restituisce il codice di errore
|
|
@(FN)
|
|
*/
|
|
|
|
int cisclose(isfd,rec,err)
|
|
isdef **isfd; /* puntatore al descrittore del file */
|
|
RecType *rec; /* buffer per il record */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
int werr = NoErr;
|
|
|
|
*err = NoErr;
|
|
if (((*isfd)->ln > 0) && ((*isfd == NULL) || (openf[(*isfd)->ln - 1] == NULL)))
|
|
{
|
|
if (*isfd != NULL)
|
|
error_box("File n. % isclose : Error n. %d ", (*isfd)->ln, IsNotOpen);
|
|
else
|
|
error_box("isclose : errore n. %d ", IsNotOpen);
|
|
}
|
|
CClose(&((*isfd)->f));
|
|
*err = ((*isfd)->f.IOR);
|
|
if ((*isfd)->r->NKeys)
|
|
{
|
|
CBCloseFile(&((*isfd)->i), &werr);
|
|
if (werr != NoErr ) *err = werr;
|
|
}
|
|
if ((*isfd)->ln > 0)
|
|
openf[(*isfd)->ln - 1] = NULL ;
|
|
if ((rec != NULL) && (*rec != NULL))
|
|
free(*rec);
|
|
relisfd(isfd);
|
|
#ifndef DOS
|
|
exclunlock(CInsPref(glockname, NORDIR), FALSE);
|
|
#endif
|
|
if (*err)
|
|
fatal_box("isclose : Error n. %d ", *err);
|
|
return (*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisstart ISAM
|
|
|
|
@(ID)
|
|
Esegue una lettura cambiando il numero di chiave attiva.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(IN)
|
|
La variabile record in input contiene i campi necessari per la ricerca,
|
|
in output contiene il record letto.
|
|
|
|
La variabile mode e' formata da un comando di lock + comando di posizionamento
|
|
. Se non si utilizza ISEQUAL o ISGREAT o ISGTEQ, il valore della variabile
|
|
record non ha nessuna importanza.
|
|
@(FN)
|
|
*/
|
|
|
|
int cisstart(isfd,keynum,record,mode,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
int keynum; /* numero della chiave */
|
|
RecType record; /* buffer per il record */
|
|
unsigned int mode; /* comando di lettura */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
if(isfd == ((isfdptr) NULL)) return ((*err = IsNotOpen));
|
|
*err = NoErr;
|
|
if(!(keynum >= 1) && (keynum <= isfd->r->NKeys))
|
|
return((*err = BTrPathErr));
|
|
isfd->i.PN = keynum - 1;
|
|
*err = cisread(isfd,record,mode,err);
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisread ISAM
|
|
|
|
@(ID)
|
|
Esegue una lettura utilizzando la chiave attiva.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
rmode = variabile che contiene il tipo lettura utilizzato.
|
|
|
|
lmode = varibaile dhe contiene il tipo lock utilizzato.
|
|
|
|
knum = numero chiave attiva.
|
|
|
|
junk = variabile spazzatura per la chiamata alla funzione "sleep".
|
|
|
|
times = variabile di lavoro.
|
|
|
|
s = stringa contenente messaggio.
|
|
|
|
w = descrittore finestra .
|
|
|
|
internaltlock = flag che verifica se la isread e' stata chiamata da iswrite per testare l' esistenza di un record.
|
|
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
La variabile record in input contiene i campi necessari per la ricerca,
|
|
in output contiene il record letto.
|
|
|
|
La variabile mode e' formata da un comando di lock + comando di posizionamento
|
|
. Se non si utilizza ISEQUAL o ISGREAT o ISGTEQ, il valore della variabile
|
|
record non ha nessuna importanza.
|
|
@(FN)
|
|
*/
|
|
|
|
int cisread(isfd,record,mode,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecType record;/* buffer per il record */
|
|
unsigned int mode; /* modo di lettura */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
unsigned int rmode = (mode & READTYPES),
|
|
lmode = (mode & RecLockTypes),
|
|
knum = (isfd->i.PN+1);
|
|
int junk,times = 1;
|
|
TKey key,key1,key2;
|
|
/* char s[120]; */
|
|
BOOLEAN internaltlock = (lmode == INTTLOCK);
|
|
|
|
if (internaltlock) lmode = ShareLock;
|
|
*err = NoErr ;
|
|
if (isfd == ((isfdptr) NULL)) return ((*err = IsNotOpen));
|
|
if (rmode & (IsPrevN + IsNextN))
|
|
{
|
|
times = rmode & BYTEMASK;
|
|
if (rmode & IsPrevN) rmode = IsPrev;
|
|
else rmode = IsNext;
|
|
}
|
|
if (rmode == IsCurr)
|
|
{
|
|
if (!isfd->RecNo) return((*err = IsNotCurr));
|
|
}
|
|
else
|
|
{
|
|
if (rmode == IsNext)
|
|
{
|
|
while ((times--) && (!*err))
|
|
{
|
|
CBNext(&isfd->i,knum,key1,&isfd->RecNo,err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rmode == IsPrev)
|
|
{
|
|
while ((times--) && (!*err))
|
|
{
|
|
CBPrev(&isfd->i,knum,key1,&isfd->RecNo,err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rmode == IsFirst) MinKey(CCalcLenKey(isfd->r,knum),key);
|
|
else
|
|
if (rmode == IsLast) MaxKey(CCalcLenKey(isfd->r,knum),key);
|
|
else
|
|
CBuildKey(isfd->r,knum,record,key);
|
|
CBRead(&isfd->i,knum,key,key1,&isfd->RecNo,err);
|
|
if ((rmode == IsGreat) && (!*err))
|
|
while ((strcmp(key,key1) == 0) && (!*err))
|
|
CBNext (&isfd->i,knum,key1,&isfd->RecNo,err);
|
|
}
|
|
}
|
|
}
|
|
do
|
|
{
|
|
if (((*err) && (rmode == IsEqual)) ||
|
|
((*err == BTrEOF) && (rmode == IsGreat)))
|
|
CRead(&isfd->f,record,isfd->RecNo,NoLock);
|
|
else
|
|
CRead(&isfd->f,record,isfd->RecNo,lmode);
|
|
if (TESTLOCK(isfd->f.IOR))
|
|
{
|
|
if (lmode == ShareLock)
|
|
{
|
|
if (!*err) *err = ISLOCKED;
|
|
break;
|
|
}
|
|
message_box("Codice %s in uso da parte\ndi un altro utente.", key1);
|
|
if (rmode != IsCurr)
|
|
{
|
|
CBReRead(&isfd->i,knum,key1,key2,isfd->RecNo,&isfd->RecNo,&junk);
|
|
if (junk) strcpy(key1, key2) ;
|
|
}
|
|
}
|
|
else
|
|
if (!*err) *err = isfd->f.IOR;
|
|
} while (TESTLOCK(isfd->f.IOR)) ;
|
|
if (((rmode == IsFirst) || (rmode == IsLast)) && (*err != BTrEmptyTree))
|
|
*err = NoErr;
|
|
if ((rmode == IsGtEq) && (*err != BTrEOF) && (*err != BTrEmptyTree))
|
|
*err = NoErr ;
|
|
if (DEADLOCK(*err)) return(*err = IsDeadLock);
|
|
if (rmode == IsCurr)
|
|
{
|
|
CBuildKey(isfd->r,knum,record,key);
|
|
CBReRead(&isfd->i,knum,key,key1,isfd->RecNo,&isfd->RecNo,&junk);
|
|
}
|
|
if (*err == BTrEmptyTree) CZeroRec(isfd->r, record);
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@($) addkeys ISAM
|
|
|
|
@(ID)
|
|
Aggiunge all'indice le chiavi contenute nel record.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
i,j = contatori.
|
|
|
|
werr = codice errore restituito dalla CBDelete.
|
|
|
|
key = valore delle chiavi.
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
@(FN)
|
|
*/
|
|
|
|
int addkeys (isfd,record,knum,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecType record; /* buffer per il record */
|
|
int knum; /* numero chiave corrente */
|
|
int *err; /* codice errore */
|
|
|
|
{
|
|
int i,j,werr;
|
|
TKey key;
|
|
|
|
for (i = 1;(i <= isfd->r->NKeys) && (!*err);i++)
|
|
{
|
|
CBuildKey(isfd->r,i,record,key);
|
|
CBWrite(&isfd->i,i,key,isfd->RecNo,err);
|
|
if (i == knum) savekeystat(isfd);
|
|
}
|
|
if (*err)
|
|
{
|
|
if (i == 2 && *err == BTrDupKeysNotAll) *err = IsReInsert;
|
|
for (j = 1; (j < i); j++)
|
|
{
|
|
CBuildKey(isfd->r,j,record,key);
|
|
CBDelete(&isfd->i,j,key,isfd->RecNo,&werr);
|
|
}
|
|
}
|
|
else restkeystat(isfd,knum);
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) ciswrite ISAM
|
|
|
|
@(ID)
|
|
Aggiunge un nuovo record al file ISAM.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
werr = codice errore restituito.
|
|
|
|
knum = numero chiave attiva.
|
|
|
|
junk = variabile di lavoro per la chiamata di varie funzioni.
|
|
|
|
wrec = buffer di lavoro.
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
La variabile record in input contiene il record da aggiungere.
|
|
@(FN)
|
|
*/
|
|
|
|
int ciswrite (isfd,record,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecType record; /* buffer per il record */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
int knum = (isfd->i.PN+1), werr, junk;
|
|
RecType wrec;
|
|
RecNoType neweox;
|
|
|
|
*err = NoErr;
|
|
if(isfd == ((isfdptr) NULL)) return((*err = IsNotOpen));
|
|
if (isfd->ln > 0)
|
|
{
|
|
COpenDir (ManuLock, isfd->ft);
|
|
COpenFile(isfd->ln,isfd->d, Lock, isfd->ft);
|
|
}
|
|
if (isfd->d->EOD == isfd->d->EOX)
|
|
{
|
|
neweox = isfd->d->EOX / 20 + 1;
|
|
if (neweox < 10) neweox = 10;
|
|
if (demoflag)
|
|
*err = IsFileFull;
|
|
else
|
|
{
|
|
neweox += isfd->d->EOX;
|
|
cisextend(isfd, isfd->ln, neweox, err);
|
|
}
|
|
if (*err == NoErr)
|
|
{
|
|
if (isfd->ln > 0)
|
|
{
|
|
COpenFile(isfd->ln,isfd->d, NoLock, isfd->ft);
|
|
for (junk = 0; junk < isfd->r->NKeys; junk++)
|
|
isfd->i.Base[junk].PEOX = neweox;
|
|
}
|
|
else
|
|
{
|
|
isfd->d->EOX = neweox;
|
|
if (isfd->f.LockMode == ExclLock)
|
|
for (junk = 0; junk < isfd->r->NKeys; junk++)
|
|
isfd->i.Base[junk].PEOX = neweox;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isfd->ln > 0)
|
|
{
|
|
COpenFile(isfd->ln,isfd->d, UnLock, isfd->ft);
|
|
CCloseDir(isfd->ft);
|
|
}
|
|
isfd->RecNo = 0;
|
|
if (DEADLOCK(*err)) *err = IsDeadLock;
|
|
return((*err ? *err : (*err = IsFileFull)));
|
|
}
|
|
}
|
|
IRecallRec(record);
|
|
if (test_share() && isfd->f.LockMode != ExclLock)
|
|
{
|
|
wrec = malloc(isfd->d->LenR);
|
|
memcpy(wrec, record, isfd->d->LenR);
|
|
savekeystat(isfd);
|
|
junk = cisstart(isfd, 1, wrec, INTTLOCK+IsEqual, &junk);
|
|
restkeystat(isfd, knum);
|
|
if ((junk == NoErr) || (junk == ISLOCKED))
|
|
{
|
|
*err = IsReInsert;
|
|
if (isfd->ln > 0)
|
|
{
|
|
COpenFile(isfd->ln,isfd->d, UnLock, isfd->ft);
|
|
CCloseDir(isfd->ft);
|
|
}
|
|
isfd->RecNo = 0;
|
|
return(*err);
|
|
}
|
|
free(wrec);
|
|
}
|
|
isfd->RecNo = (++isfd->d->EOD);
|
|
if ((isfd->r->NKeys) && IndActive)
|
|
{
|
|
if(test_share() && isfd->f.LockMode != ExclLock)
|
|
CBLockFile(&isfd->i,err) ;
|
|
if (!addkeys(isfd, record, knum, err))
|
|
{
|
|
CWrite(&isfd->f,record,isfd->RecNo,NoLock);
|
|
if ((*err = isfd->f.IOR))
|
|
{
|
|
isfd->RecNo = 0;
|
|
junk = delkeys(isfd, record, knum, &werr);
|
|
}
|
|
else
|
|
if (isfd->ln > 0)
|
|
CCloseFile(isfd->ln,isfd->d, isfd->ft) ;
|
|
}
|
|
else isfd->d->EOD-- ;
|
|
if(test_share() && isfd->f.LockMode != ExclLock)
|
|
CBUnLockFile(&isfd->i, &werr) ;
|
|
}
|
|
else
|
|
{
|
|
CWrite(&isfd->f,record,isfd->RecNo,NoLock);
|
|
if ((*err = isfd->f.IOR)) isfd->RecNo = 0;
|
|
else CCloseFile(isfd->ln,isfd->d, isfd->ft) ;
|
|
}
|
|
if (!(*err))
|
|
{
|
|
#ifndef DOS
|
|
if (isstate == NOTRANS) writelog(FNWRITE, isfd, record);
|
|
else writeundo(FNWRITE, isfd, record);
|
|
#endif
|
|
}
|
|
if (isfd->ln > 0)
|
|
CCloseDir(isfd->ft);
|
|
if (test_share())
|
|
{
|
|
junk = cisunlock(isfd, &junk);
|
|
if (isstate == NOTRANS)
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
if (DEADLOCK(*err)) *err = IsDeadLock;
|
|
}
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@($) delkeys ISAM
|
|
|
|
@(ID)
|
|
Cancella le chiavi contenute nel record dall'indice.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
i,j = contatori.
|
|
|
|
werr = codice errore da CBWrite.
|
|
|
|
key = valori chiave.
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
@(FN)
|
|
*/
|
|
|
|
int delkeys (isfd,record,knum,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecType record; /* buffer per il record */
|
|
int knum; /* numero della chiave attuale */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
int i,j,werr;
|
|
TKey key;
|
|
|
|
for (i = 1;(i <= isfd->r->NKeys)&&(!*err);i++)
|
|
{
|
|
CBuildKey(isfd->r,i,record,key);
|
|
CBDelete(&isfd->i,i,key,isfd->RecNo,err);
|
|
if (i == knum) savekeystat(isfd);
|
|
}
|
|
if (*err)
|
|
{
|
|
for (j = 1;(j < i);j++)
|
|
{
|
|
CBuildKey(isfd->r,j,record,key);
|
|
CBWrite(&isfd->i,j,key,isfd->RecNo,&werr);
|
|
}
|
|
}
|
|
else restkeystat(isfd,knum);
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisdelete ISAM
|
|
|
|
@(ID)
|
|
Cancella un record da un file ISAM.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
knum = numero chiave successiva a quella attiva.
|
|
|
|
werr = codice errore da CBUnLockFile.
|
|
|
|
key1,key = valori chiave.
|
|
|
|
- Versione DOS e XENIX
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
La variabile record in input contiene il record da cancellare.
|
|
@(FN)
|
|
*/
|
|
|
|
int cisdelete(isfd,record,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecType record; /* buffer per il record */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
int knum = (isfd->i.PN+1), werr;
|
|
TKey key,key1;
|
|
|
|
if(isfd == ((isfdptr) NULL)) return((*err = IsNotOpen));
|
|
*err = NoErr;
|
|
savekeystat(isfd);
|
|
CBuildKey(isfd->r,1,record,key);
|
|
*err = NoErr ;
|
|
CBRead(&isfd->i,1,key,key1,&isfd->RecNo,err);
|
|
if (*err)
|
|
{
|
|
restkeystat(isfd,knum);
|
|
return(*err);
|
|
}
|
|
CRead(&isfd->f, record, isfd->RecNo, NoLock);
|
|
if ((*err = isfd->f.IOR))
|
|
{
|
|
restkeystat(isfd,knum);
|
|
return(*err);
|
|
}
|
|
if ((isfd->r->NKeys) && IndActive)
|
|
{
|
|
if(test_share() && isfd->f.LockMode != ExclLock)
|
|
CBLockFile(&isfd->i,err) ;
|
|
delkeys(isfd, record, knum, err) ;
|
|
}
|
|
IDeleteRec(record);
|
|
CWrite(&isfd->f,record,isfd->RecNo,UnLock);
|
|
if((*err = isfd->f.IOR))
|
|
{
|
|
IRecallRec(record);
|
|
CWrite(&isfd->f,record,isfd->RecNo,NoLock);
|
|
if ((isfd->r->NKeys) && IndActive) addkeys(isfd, record, knum, err) ;
|
|
restkeystat(isfd,knum);
|
|
}
|
|
#ifndef DOS
|
|
else
|
|
{
|
|
if (isstate == NOTRANS)
|
|
{
|
|
writelog(FNDELETE, isfd, NULL);
|
|
CRead(&isfd->f,record,isfd->RecNo,UnLock);
|
|
}
|
|
else writeundo(FNDELETE, isfd, NULL);
|
|
}
|
|
if (test_share() && (isfd->r->NKeys) && IndActive &&
|
|
(isfd->f.LockMode != ExclLock))
|
|
CBUnLockFile(&isfd->i, &werr) ;
|
|
#else
|
|
if (test_share())
|
|
{
|
|
CRead(&isfd->f,record,isfd->RecNo,UnLock);
|
|
if (isfd->r->NKeys && IndActive &&
|
|
(isfd->f.LockMode != ExclLock))
|
|
CBUnLockFile(&isfd->i, &werr) ;
|
|
}
|
|
#endif
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@($) replkeys ISAM
|
|
|
|
@(ID)
|
|
Rimpiazza le chiavi all'interno dell'indice.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
i,j = contatori.
|
|
|
|
werr = codice errore ritornato da CBDelete e CBWrite.
|
|
|
|
key,key1 = valori delle chiavi.
|
|
@(FSV)
|
|
*/
|
|
|
|
int replkeys (isfd,oldrec,record,knum,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecType oldrec; /* buffer contenente il vecchio record */
|
|
RecType record; /* buffer contenente il nuovo record */
|
|
int knum; /* numero della chiave attuale */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
int i,j,werr;
|
|
TKey key,key1;
|
|
|
|
for (i = 1;(i <= isfd->r->NKeys)&&(!*err);i++)
|
|
{
|
|
CBuildKey(isfd->r,i,record,key);
|
|
CBuildKey(isfd->r,i,oldrec,key1);
|
|
if (strcmp(key,key1) != 0)
|
|
{
|
|
CBDelete(&isfd->i,i,key1,isfd->RecNo,err);
|
|
if (*err) break;
|
|
CBWrite(&isfd->i,i,key,isfd->RecNo,err);
|
|
if (*err) CBWrite(&isfd->i,i,key1,isfd->RecNo,err);
|
|
if (i == knum) savekeystat(isfd);
|
|
}
|
|
}
|
|
if (*err)
|
|
{
|
|
for (j = 1;(j < i);j++)
|
|
{
|
|
CBuildKey(isfd->r,j,record,key);
|
|
CBuildKey(isfd->r,j,oldrec,key1);
|
|
if (strcmp(key,key1) != 0)
|
|
{
|
|
CBDelete (&isfd->i,j,key,isfd->RecNo,&werr);
|
|
CBWrite(&isfd->i,j,key1,isfd->RecNo,&werr);
|
|
}
|
|
}
|
|
}
|
|
else restkeystat(isfd,knum);
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisrewrite ISAM
|
|
|
|
@(ID)
|
|
Aggiorna un record nel file ISAM.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(ISV)
|
|
knum = numero chiave successiva all'attuale.
|
|
|
|
werr = codice errore restituito da CBUnLock.
|
|
|
|
key, key1 = valori delle chiavi.
|
|
|
|
oldrec = buffer di lavoro.
|
|
|
|
- Versione DOS e XENIX
|
|
@(FSV)
|
|
|
|
@(IN)
|
|
La variabile record in input contiene il record da aggiornare.
|
|
Utilizza la chiave 1 per ritrovare il record da aggiornare.
|
|
@(FN)
|
|
*/
|
|
|
|
int cisrewrite(isfd,record,err)
|
|
isfdptr isfd; /* descrittore del file isam */
|
|
RecType record; /* buffer contenente i record */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
int knum = (isfd->i.PN+1), werr;
|
|
TKey key,key1;
|
|
RecType oldrec;
|
|
|
|
*err = NoErr ;
|
|
if(isfd == ((isfdptr) NULL)) return((*err = IsNotOpen));
|
|
oldrec = (RecType) malloc(isfd->d->LenR);
|
|
savekeystat(isfd);
|
|
IRecallRec(record);
|
|
CBuildKey(isfd->r,1,record,key);
|
|
CBRead(&isfd->i,1,key,key1,&isfd->RecNo,err);
|
|
if(*err)
|
|
{
|
|
restkeystat(isfd,knum);
|
|
return(*err);
|
|
}
|
|
CRead(&isfd->f,oldrec,isfd->RecNo,NoLock);
|
|
if ((*err = isfd->f.IOR))
|
|
{
|
|
restkeystat(isfd,knum);
|
|
free(oldrec);
|
|
return(*err);
|
|
}
|
|
if (memcmp(oldrec,record,isfd->d->LenR) == 0)
|
|
{
|
|
*err = NoErr;
|
|
restkeystat(isfd,knum);
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
free(oldrec);
|
|
return(*err);
|
|
}
|
|
if ((isfd->r->NKeys) && IndActive)
|
|
{
|
|
if(test_share() && isfd->f.LockMode != ExclLock)
|
|
CBLockFile(&isfd->i, err) ;
|
|
replkeys(isfd, oldrec, record, knum, err) ;
|
|
if(test_share() && isfd->f.LockMode != ExclLock)
|
|
CBUnLockFile(&isfd->i, &werr) ;
|
|
}
|
|
CWrite(&isfd->f,record,isfd->RecNo,NoLock);
|
|
if ((*err = isfd->f.IOR))
|
|
{
|
|
CWrite(&isfd->f,oldrec,isfd->RecNo,NoLock);
|
|
replkeys(isfd, record, oldrec, knum, err) ;
|
|
restkeystat(isfd,knum);
|
|
}
|
|
else
|
|
#ifndef DOS
|
|
{
|
|
if (isstate == NOTRANS)
|
|
{
|
|
writelog(FNREWRITE, isfd, record);
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
}
|
|
else writeundo(FNREWRITE, isfd, oldrec);
|
|
}
|
|
|
|
#else
|
|
if (test_share())
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
#endif
|
|
free(oldrec);
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisdelcurr ISAM
|
|
|
|
@(ID)
|
|
Cancella il record corrente.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
*/
|
|
|
|
int cisdelcurr(isfd,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
if(isfd->RecNo) cisdelrec(isfd,isfd->RecNo,err);
|
|
else *err = IsNotCurr;
|
|
return(*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisrewcurr ISAM
|
|
|
|
@(ID)
|
|
Riscrive il record corrente.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
|
|
@(IN)
|
|
La variabile record in input contiene il record da aggiornare.
|
|
@(FN)
|
|
*/
|
|
|
|
int cisrewcurr(isfd,record,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecType record; /* buffer contenente il record */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
if(isfd->RecNo) cisrewrec(isfd,isfd->RecNo,record,err);
|
|
else *err = IsNotCurr;
|
|
return (*err);
|
|
}
|
|
|
|
/*
|
|
@(#) cisreadrec ISAM
|
|
|
|
@(ID)
|
|
Legge un record di numero "recnum".
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
*/
|
|
|
|
int cisreadrec(isfd,recnum,record,mode,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecNoType recnum; /* numero del record */
|
|
RecType record; /* buffer per il record */
|
|
unsigned int mode; /* modo di lock */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
isfd->RecNo = recnum;
|
|
return(cisread(isfd,record,IsCurr+(mode & RecLockTypes),err));
|
|
}
|
|
|
|
/*
|
|
@(#) ciswriterec ISAM
|
|
|
|
@(ID)
|
|
Riscrive un record di numero "recnum".
|
|
@(FD)
|
|
|
|
@(IN)
|
|
La variabile record in input contiene il record da aggiornare.
|
|
@(FN)
|
|
|
|
@(ISV)
|
|
knum = numero chiave attiva.
|
|
|
|
werr = codice errore restituito da CBUnLockFile.
|
|
|
|
oldrec = buffer di lavoro.
|
|
|
|
- Versione DOS e XENIX
|
|
@(FSV)
|
|
*/
|
|
|
|
int cisrewrec(isfd,recnum,record,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecNoType recnum; /* numero del record da riscrivere */
|
|
RecType record; /* buffer per il record */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
int knum = (isfd->i.PN+1), werr;
|
|
RecType oldrec;
|
|
|
|
*err = NoErr;
|
|
if (isfd == ((isfdptr) NULL)) return ((*err = IsNotOpen));
|
|
oldrec = (RecType) malloc(isfd->d->LenR);
|
|
isfd->RecNo = recnum;
|
|
IRecallRec(record);
|
|
CRead(&isfd->f,oldrec,isfd->RecNo,NoLock);
|
|
if ((*err = isfd->f.IOR))
|
|
{
|
|
free(oldrec);
|
|
return(*err);
|
|
}
|
|
if (memcmp(oldrec,record,isfd->d->LenR) == 0)
|
|
{
|
|
*err = NoErr;
|
|
if (test_share())
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
free(oldrec);
|
|
return(*err);
|
|
}
|
|
if ((isfd->r->NKeys) && IndActive)
|
|
{
|
|
if (test_share() && isfd->f.LockMode != ExclLock)
|
|
CBLockFile(&isfd->i, err) ;
|
|
replkeys(isfd, oldrec, record, knum, err) ;
|
|
if (test_share() && isfd->f.LockMode != ExclLock)
|
|
CBUnLockFile(&isfd->i, &werr) ;
|
|
}
|
|
if (isstate == NOTRANS) CWrite(&isfd->f,record,isfd->RecNo,UnLock);
|
|
else CWrite(&isfd->f,record,isfd->RecNo,NoLock);
|
|
if ((*err = isfd->f.IOR))
|
|
{
|
|
CWrite(&isfd->f,oldrec,isfd->RecNo,NoLock);
|
|
replkeys(isfd, record, oldrec, knum, err) ;
|
|
}
|
|
#ifndef DOS
|
|
else
|
|
{
|
|
if (isstate == NOTRANS)
|
|
{
|
|
writelog(FNREWRITE, isfd, record);
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
}
|
|
else writeundo(FNREWRITE, isfd, oldrec);
|
|
}
|
|
#else
|
|
if (test_share())
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
#endif
|
|
free(oldrec);
|
|
return(*err);
|
|
}
|
|
/*
|
|
@(#) cisdelrec ISAM
|
|
@(ID)
|
|
Cancella un record utilizzando un numero di record.
|
|
Ritorna il codice di errore.
|
|
@(FD)
|
|
@(IN)
|
|
La variabile record in input contiene il record da cancellare.
|
|
@(FN)
|
|
@(ISV)
|
|
knum = numero della chiave attiva.
|
|
werr = codice di errore restituito da CBUnLockFiles.
|
|
oldrec = buffer di lavoro.
|
|
key1 = valore della chiave.
|
|
- Versione DOS e XENIX
|
|
@(FSV)
|
|
*/
|
|
int cisdelrec(isfd,recnum,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecNoType recnum; /* numero di record */
|
|
int *err; /* codice di errore */
|
|
{
|
|
int knum = (isfd->i.PN+1), werr;
|
|
int junk;
|
|
RecType oldrec ;
|
|
TKey key1 ;
|
|
*err = NoErr;
|
|
if(isfd == (isfdptr) NULL) return ((*err = IsNotOpen));
|
|
oldrec = (RecType) malloc(isfd->d->LenR);
|
|
isfd->RecNo = recnum;
|
|
CRead(&isfd->f, oldrec, isfd->RecNo, NoLock);
|
|
if ((*err = isfd->f.IOR))
|
|
{
|
|
free(oldrec);
|
|
return(*err);
|
|
}
|
|
if ((isfd->r->NKeys) && IndActive)
|
|
{
|
|
if(test_share() && isfd->f.LockMode != ExclLock)
|
|
CBLockFile(&isfd->i, err) ;
|
|
delkeys(isfd, oldrec, knum, err);
|
|
}
|
|
IDeleteRec(oldrec);
|
|
CWrite(&isfd->f,oldrec,isfd->RecNo,UnLock);
|
|
if ((*err = isfd->f.IOR))
|
|
{
|
|
IRecallRec(oldrec);
|
|
CWrite(&isfd->f,oldrec,isfd->RecNo,NoLock);
|
|
if ((isfd->r->NKeys) && IndActive) addkeys(isfd, oldrec, knum, err);
|
|
}
|
|
#ifndef DOS
|
|
else
|
|
{
|
|
if (isstate == NOTRANS)
|
|
{
|
|
writelog(FNDELETE, isfd, NULL);
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
}
|
|
else writeundo(FNDELETE, isfd, NULL);
|
|
}
|
|
if (test_share() && (isfd->r->NKeys) && IndActive && (isfd->f.LockMode != ExclLock))
|
|
CBUnLockFile(&isfd->i, &werr) ;
|
|
#else
|
|
if (test_share())
|
|
{
|
|
CLockRec(&isfd->f,isfd->RecNo,UnLock);
|
|
if (isfd->r->NKeys && IndActive &&
|
|
(isfd->f.LockMode != ExclLock))
|
|
CBUnLockFile(&isfd->i, &werr) ;
|
|
}
|
|
#endif
|
|
free(oldrec);
|
|
isfd->RecNo = 0;
|
|
return(*err);
|
|
}
|
|
/*
|
|
@(#) cisgetrecno ISAM
|
|
@(ID)
|
|
Restituisce il numero del record corrente.
|
|
@(FD)
|
|
*/
|
|
RecNoType cisgetrecno(isfd, err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
int *err; /* codice di errore */
|
|
|
|
{
|
|
if (!isfd->RecNo) *err = IsNotCurr;
|
|
else *err = NoErr;
|
|
return(isfd->RecNo);
|
|
}
|
|
/*
|
|
@(#) cislock ISAM
|
|
@(ID)
|
|
Blocca il file ISAM.
|
|
@(FD)
|
|
@(ISV)
|
|
junk = variabile spazzatura per la chiamata di sleep.
|
|
@(FSV)
|
|
*/
|
|
int cislock(isfd,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
int *err; /* codice di errore */
|
|
{
|
|
int junk;
|
|
*err = NoErr ;
|
|
if (lseek(isfd->f.F, 0L, 0) == -1) return ((*err = CIOResult()));
|
|
#ifndef DOS
|
|
do
|
|
{
|
|
if (lockf(isfd->f.F,F_TLOCK,0L) == -1)
|
|
{
|
|
*err = CIOResult() ;
|
|
junk = sleep(1) ;
|
|
}
|
|
} while (TESTLOCK(*err)) ;
|
|
#endif
|
|
if(test_share() && isfd->f.LockMode != ExclLock)
|
|
CBLockFile(&isfd->i,err);
|
|
return(*err);
|
|
}
|
|
/*
|
|
@(#) cisunlock ISAM
|
|
@(ID)
|
|
Sblocca un file ISAM.
|
|
@(FD)
|
|
*/
|
|
int cisunlock(isfd,err)
|
|
isfdptr isfd; /* descrittore del file */
|
|
int *err; /* codice di errore */
|
|
{
|
|
return(cisrelease(isfd,err));
|
|
}
|
|
/*
|
|
@(#) cisrelease ISAM
|
|
@(ID)
|
|
Sblocca un file ISAM.
|
|
@(FD)
|
|
*/
|
|
int cisrelease(isfd,err)
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
int *err; /* codice di errore */
|
|
{
|
|
*err = NoErr ;
|
|
#ifndef DOS
|
|
if (lseek(isfd->f.F, 0L, 0) == -1) return ((*err = CIOResult()));
|
|
do
|
|
{
|
|
if (lockf(isfd->f.F,F_ULOCK,0L) == -1) *err = CIOResult() ;
|
|
} while (TESTLOCK(*err)) ;
|
|
#endif
|
|
if(test_share() && isfd->f.LockMode != ExclLock)
|
|
CBUnLockFile(&isfd->i,err);
|
|
return(*err);
|
|
}
|
|
/*
|
|
@(#) IndexOn ISAM
|
|
@(ID)
|
|
Attiva Aggiornamento Indici.
|
|
@(FD)
|
|
@(IN)
|
|
Di default gli indici sono attivi.
|
|
@(FN)
|
|
*/
|
|
void IndexOn()
|
|
{
|
|
IndActive = TRUE ;
|
|
}
|
|
/*
|
|
@(#) IndexOff ISAM
|
|
@(ID)
|
|
Disattiva l'aggiornamento Indici.
|
|
@(FD)
|
|
*/
|
|
void IndexOff()
|
|
{
|
|
IndActive = FALSE ;
|
|
}
|
|
#ifndef DOS
|
|
/*
|
|
@($) undoname ISAM
|
|
@(ID)
|
|
Restituisce il nome del file di Undo.
|
|
@(FD)
|
|
@(ISV)
|
|
path = stringa contenente il nome file.
|
|
@(FSV)
|
|
*/
|
|
char *undoname()
|
|
{
|
|
static PathSt path;
|
|
TMPFNAME(path, "undo");
|
|
return(path);
|
|
}
|
|
/*
|
|
@($) writeundo ISAM
|
|
@(ID)
|
|
Scrive una operazione effettuata nel file di Undo.
|
|
@(FD)
|
|
@(ISV)
|
|
fd = puntatore al file.
|
|
uname = nome del file di undo.
|
|
lgh = variabile di lavoro che contiene l' header del record di undo.
|
|
@(FSV)
|
|
*/
|
|
void writeundo(fntype,isfd,record)
|
|
int fntype; /* operazione da effettuare */
|
|
isfdptr isfd; /* descrittore del file */
|
|
RecType record; /* buffer contenente il record */
|
|
{
|
|
int fd;
|
|
PathSt uname;
|
|
loghead lgh;
|
|
|
|
if (isfd->ln <= 0) return ;
|
|
strcpy(uname ,undoname());
|
|
if ((fd = open(uname, O_WRONLY | O_CREAT | O_APPEND, 0666)) == -1)
|
|
fatal_box("Writeundo : Error n. %d ", errno);
|
|
lgh.type = fntype;
|
|
lgh.time = time(NULL);
|
|
lgh.procid = getpid();
|
|
lgh.userid = getuid();
|
|
lgh.filenum = isfd->ln;
|
|
lgh.recnum = isfd->RecNo;
|
|
lgh.lenrec = isfd->d->LenR;
|
|
if (write(fd, &lgh, sizeof(lgh)) == -1)
|
|
fatal_box("Writeundo : Error n. %d ", errno);
|
|
if (fntype & (FNREWRITE))
|
|
if (write(fd, record, lgh.lenrec) == -1)
|
|
fatal_box("Writeundo : Error n. %d ", errno);
|
|
if (close(fd) == -1)
|
|
fatal_box("Writeundo : Error n. %d ", errno);
|
|
}
|
|
/*
|
|
@($) writelog ISAM
|
|
@(ID)
|
|
Scrive sul file Giornale l'operazione effettuata.
|
|
@(FD)
|
|
@(ISV)
|
|
junk = variabile spazzatura per la chiamata di execunlock.
|
|
lname = nome del file Giornale (LOG).
|
|
fd = puntatore al file giornale.
|
|
lgh = testata del file giornale.
|
|
@(FSV)
|
|
*/
|
|
void writelog(fntype,isfd,record)
|
|
int fntype; /* operazione effetuata */
|
|
isfdptr isfd; /* descrittore del file ISAM */
|
|
RecType record; /* buffer per il record */
|
|
{
|
|
int fd,junk;
|
|
PathSt lname;
|
|
loghead lgh;
|
|
if (!isjournal) return;
|
|
if (isfd->ln <= 0) return ;
|
|
strcpy(lname, CInsPref(logname, NORDIR));
|
|
while (excllock(lname,TRUE) == -1) sleep(1);
|
|
if ((fd = open(lname, O_WRONLY | O_CREAT | O_APPEND, 0666)) == -1)
|
|
{
|
|
junk = exclunlock(lname,TRUE);
|
|
fatal_box("Writelog : Error n. %d ", errno);
|
|
}
|
|
lgh.type = fntype + FNSTTRANS;
|
|
lgh.time = time(NULL);
|
|
lgh.procid = getpid();
|
|
lgh.userid = getuid();
|
|
if (fntype & (FNREWRITE + FNWRITE + FNDELETE))
|
|
{
|
|
lgh.filenum = isfd->ln;
|
|
lgh.recnum = isfd->RecNo;
|
|
lgh.lenrec = isfd->d->LenR;
|
|
}
|
|
else
|
|
{
|
|
lgh.filenum = 0;
|
|
if (fntype == FNREORG) lgh.recnum = *((RecNoType *) record);
|
|
else lgh.recnum = 0L;
|
|
if (fntype == FNCHGREC) lgh.lenrec = sizeof(RecDes);
|
|
else lgh.lenrec = 0;
|
|
}
|
|
if (write(fd, &lgh, sizeof(lgh)) == -1)
|
|
{
|
|
junk = exclunlock(lname,TRUE);
|
|
fatal_box("Writelog : Error n. %d ", errno);
|
|
}
|
|
if (fntype & (FNREWRITE + FNWRITE + FNCHGREC))
|
|
if (write(fd, record, lgh.lenrec) == -1)
|
|
{
|
|
junk = exclunlock(lname,TRUE);
|
|
fatal_box("Writelog : Error n. %d ", errno);
|
|
}
|
|
if (close(fd) == -1)
|
|
fatal_box("Writelog : Error n. %d ", errno);
|
|
junk = exclunlock(lname,TRUE);
|
|
}
|
|
#endif
|
|
/*
|
|
@(#) StTrans ISAM
|
|
@(ID)
|
|
Inizia una transazione.
|
|
@(FD)
|
|
*/
|
|
void StTrans()
|
|
{
|
|
#ifndef DOS
|
|
if (isstate == TRANS) EndTrans();
|
|
#endif
|
|
isstate = TRANS;
|
|
}
|
|
#ifndef DOS
|
|
/*
|
|
@($) getopenf ISAM
|
|
@(ID)
|
|
Riconfigura il file di lavoro attivo sul file di numero logico "ln".
|
|
@(FD)
|
|
@(ISV)
|
|
junk = variabile spazzatura per la chiamata alla cisclose.
|
|
err = codice di errore ritornato dalla cisopen.
|
|
@(FSV)
|
|
*/
|
|
void getopenf(ln,record)
|
|
int ln; /* numero logico del file */
|
|
RecType *record; /* puntatore al buffer per il record */
|
|
{
|
|
int err,junk;
|
|
if (openf[ln - 1] == NULL)
|
|
{
|
|
if (wln != ln)
|
|
{
|
|
if (wln != -1) junk = cisclose(&wisfd ,record ,&err);
|
|
cisopen(&wisfd, ln, record, ManuLock, &err);
|
|
wln = ln;
|
|
}
|
|
}
|
|
else *record = realloc(*record, openf[ln - 1]->d->LenR);
|
|
}
|
|
#endif
|
|
/*
|
|
@(#) EndTrans ISAM
|
|
@(ID)
|
|
Chiude una transazione.
|
|
@(FD)
|
|
@(ISV)
|
|
fdl, fdu = puntatori ai file di LOG e di Undo.
|
|
lname, uname = nomi dei file di LOG e di Undo.
|
|
lgh, lgh1 = variabili di lavoro contenenti le testate dei file di log.
|
|
nread = variabile di lavoro per la chiamata alla read.
|
|
werr = codice di errore ritornato dalla cisclose.
|
|
junk = variabile spazzatura per la chiamata di exclunlock.
|
|
start = variabile di lavoro.
|
|
record = buffer di lavoro.
|
|
@(FSV)
|
|
*/
|
|
void EndTrans()
|
|
{
|
|
#ifndef DOS
|
|
int fdl, fdu;
|
|
PathSt lname, uname;
|
|
loghead lgh, lgh1;
|
|
int nread, werr, junk, start = FNSTTRANS;
|
|
RecType record;
|
|
strcpy(lname ,CInsPref(logname, NORDIR));
|
|
while (excllock(lname,TRUE) == -1) sleep(1);
|
|
if (((fdl = open(lname, O_WRONLY | O_CREAT | O_APPEND, 0666)) == -1) ||
|
|
((fdu = open(uname, O_RDONLY, 0666)) == -1))
|
|
{
|
|
junk = exclunlock(lname,TRUE);
|
|
fatal_box("Endtrans : Error n. %d ", errno);
|
|
}
|
|
while ((nread = read(fdu, &lgh, sizeof(lgh))) > 0)
|
|
{
|
|
lgh.type += start;
|
|
start = 0;
|
|
if (write(fdl, &lgh, sizeof(lgh)) == -1)
|
|
{
|
|
junk = exclunlock(lname,TRUE);
|
|
fatal_box("Endtrans : Error n. %d ", errno);
|
|
}
|
|
if (lgh.type == FNREWRITE)
|
|
if (lseek(fdu, (long) lgh.lenrec, 1) == -1)
|
|
{
|
|
junk = exclunlock(lname,TRUE);
|
|
fatal_box("Endtrans : Error n. %d ", errno);
|
|
}
|
|
getopenf(lgh.filenum, &record);
|
|
CRead(&(openf[lgh.filenum - 1]->f), record, lgh.recnum, UnLock);
|
|
if (write(fdl, record, lgh.lenrec) == -1)
|
|
{
|
|
junk = exclunlock(lname,TRUE);
|
|
fatal_box("Endtrans : Error n. %d ", errno);
|
|
}
|
|
}
|
|
if ((nread <= 0) || (close(fdu) == -1) || (close(fdl) == -1) ||
|
|
(unlink(uname) == -1))
|
|
{
|
|
junk = exclunlock(lname,TRUE);
|
|
fatal_box("Endtrans : Error n. %d ", errno);
|
|
}
|
|
if (wln != -1)
|
|
{
|
|
junk = cisclose(&wisfd, &record, &werr);
|
|
wln = -1;
|
|
}
|
|
junk = exclunlock(lname,TRUE);
|
|
#endif
|
|
}
|
|
/*
|
|
@(#) AbTrans ISAM
|
|
@(ID)
|
|
Abortisce una transazione.
|
|
@(FD)
|
|
*/
|
|
void AbTrans()
|
|
{
|
|
#ifndef DOS
|
|
int fd;
|
|
PathSt uname;
|
|
loghead lgh;
|
|
int nread, werr, junk;
|
|
RecType record;
|
|
RecType oldrec;
|
|
strcpy(uname ,undoname());
|
|
if ((fd = open(uname, O_RDONLY, 0666)) == -1)
|
|
fatal_box("Abtrans : Error n. %d ", errno);
|
|
while ((nread = read(fd, &lgh, sizeof(lgh))) > 0)
|
|
{
|
|
getopenf(lgh.filenum, &record);
|
|
if (oldrec == NULL) oldrec = malloc(lgh.lenrec);
|
|
else oldrec = realloc(oldrec, lgh.lenrec);
|
|
if (lgh.type & (FNREWRITE))
|
|
{
|
|
if ((nread = read(fd, record, lgh.lenrec)) <= 0)
|
|
fatal_box("Abtrans : Error n. %d ", errno);
|
|
}
|
|
if (lgh.lenrec != openf[lgh.filenum - 1]->d->LenR)
|
|
fatal_box("Abtrans : Error n. %d ", IsNoMatch);
|
|
CRead(&(openf[lgh.filenum - 1]->f), oldrec, lgh.recnum, NoLock);
|
|
switch (lgh.type)
|
|
{
|
|
case FNREWRITE :
|
|
junk = replkeys(openf[lgh.filenum - 1], oldrec, record,
|
|
openf[lgh.filenum - 1]->i.PN + 1, &werr);
|
|
CWrite(&(openf[lgh.filenum - 1]->f), record, lgh.recnum, UnLock);
|
|
break;
|
|
case FNDELETE :
|
|
IRecallRec(oldrec);
|
|
junk = addkeys(openf[lgh.filenum - 1], oldrec,
|
|
openf[lgh.filenum - 1]->i.PN + 1, &werr);
|
|
CWrite(&(openf[lgh.filenum - 1]->f), oldrec, lgh.recnum, UnLock);
|
|
break;
|
|
case FNWRITE :
|
|
IDeleteRec(oldrec);
|
|
junk = delkeys(openf[lgh.filenum - 1], oldrec,
|
|
openf[lgh.filenum - 1]->i.PN + 1, &werr);
|
|
CWrite(&(openf[lgh.filenum - 1]->f), record, lgh.recnum, UnLock);
|
|
break;
|
|
}
|
|
}
|
|
if ((nread == -1) || (close(fd) == -1) || (unlink(uname) == -1))
|
|
fatal_box("Abtrans : Error n. %d ", errno);
|
|
if (wln != -1)
|
|
{
|
|
junk = cisclose(&wisfd, &record, &werr);
|
|
wln = -1;
|
|
}
|
|
#endif
|
|
}
|
|
|