home *** CD-ROM | disk | FTP | other *** search
- /* ==( io/src/ictree.c )== */
-
- /* ----------------------------------------------- */
- /* Pro-C Copyright (C) 1988 - 1990 Vestronix Inc. */
- /* Modification to this source is not supported */
- /* by Vestronix Inc. */
- /* All Rights Reserved */
- /* ----------------------------------------------- */
- /* Written SBF 01-Aug-89 */
- /* Modified VvA 28-Feb-90 see notes below */
- /* ----------------------------------------------- */
- /* %W% (%H% %T%) */
-
- /*
- * Modifications
- *
- * 28-Mar-90 VvA - adjustments for locking modes, transactions
- * 16-Feb-90 VvA - IOGEN version, key segments enabled
- * 20-Aug-89 SBF
- */
-
- /*
- * C-TREE I/O calls via general IOGEN.C interface
- * (for C-Tree 4.3B and beyond)
- *
- *****************************************************************************
- * *
- * *** NOTE *** : For UNIX systems two modifications to C-Tree code are *
- * required. Change calls to creat() to calls to open() *
- * with O_RDWR | O_CREAT | O_TRUNC as the second argument. *
- * Also, in the function CREIDX() where the other indices *
- * ct_num->chnacs are being set to 'm' increment ct_num *
- * before entering the loop through all the members. *
- * *
- *****************************************************************************
- */
-
- # include <stdio.h>
- # include <iodef.h>
- # include <iomsg.h>
- # include <proc.io>
- # include <bench.h>
- # include <iosup.h>
- # include <ctype.h>
-
- #ifdef QNX
- #include <file_io.h>
- #else
- #include <fileio.h>
- #endif
-
- #include <ctport.h>
- #include <ctoptn.h>
- #include <ctstrc.h>
- #include <ctisam.h>
- #include <ctifil.h>
- #include <cterrc.h>
- #include <ctgvar.h>
-
- /*
- * Macro definitions
- */
- #define INDEX_BUFFERS 6 /* These three are the parameters */
- #define MAX_FILES_USED 20 /* used for an INTREE() call... */
- #define NUM_INDEX_SECTS 4 /* If you increase MAX_FILES then */
- /* increase MAX_FILES_USED... */
- #define RLOCKON 2
- #define WLOCKON 1
- #define LOCKOFF 0
-
-
- /* Function prototypes */
- # ifdef ANSI
- static int i_addrec(int, char *);
- static int i_close_file(int, char *);
- static int i_commit(int, char *);
- static int i_delrec(int, char *);
- static int i_filename(int, char *);
- static int i_findkey(int, char *);
- static int i_firstkey(int, char *);
- static int i_init_file(int, char *);
- static int i_lastkey(int, char *);
- static int i_lockrec(int, char *);
- static int i_login(int, char *);
- static int i_logoff(int, char *);
- static int i_nextrec(int, char *);
- static int i_open_file(int, char *);
- static int i_prevrec(int, char *);
- static int i_rereadrec(int, char *);
- static int i_rollback(int, char *);
- static int i_selectinx(int, char *);
- static int i_transact(int, char *);
- static int i_unlock_rec(int, char *);
- static int i_updrec(int, char *);
- static int io_xlate(int, int, char *);
- static int add_rec(int, char *);
- static int cl_ifil(IFIL *);
- static int cre_ifil(IFIL *);
- static int del_rec(int);
- static int frm_key(int, int, char *, char *, long);
- static int gte_rec(int, char *, char *);
- static int lst_rec(int, char *);
- static int nxt_rec(int, char *);
- static int opn_ifil(IFIL *);
- static int prv_rec(int, char *);
- static int rrd_rec(int, char *);
- static int rwt_rec(int, char *);
- static int create_file(int);
- static int get_mode(int);
- static int length_check(int);
- static int load_keys(int);
- static int lockit(int, long, int);
- /* externs from C-Tree */
- EXTERN COUNT ADDKEY(COUNT, TEXT *, POINTER, COUNT);
- EXTERN COUNT CLSFIL(COUNT, COUNT);
- EXTERN COUNT CREDAT(COUNT, TEXT *, UCOUNT, UCOUNT, COUNT);
- EXTERN COUNT CREIDX(COUNT, TEXT *, COUNT, COUNT, COUNT, COUNT, UCOUNT, COUNT);
- EXTERN COUNT CREMEM(COUNT, COUNT, COUNT, COUNT, COUNT);
- EXTERN COUNT DELCHK(COUNT, TEXT *, POINTER);
- EXTERN POINTER GTEKEY(COUNT, TEXT *, TEXT *);
- EXTERN POINTER GTKEY(COUNT, TEXT *, TEXT *);
- EXTERN COUNT INTREE(COUNT, COUNT, COUNT);
- EXTERN COUNT LOKREC(COUNT, COUNT, POINTER);
- EXTERN COUNT LSTKEY(COUNT, TEXT *);
- EXTERN POINTER LTKEY(COUNT, TEXT *, TEXT *);
- EXTERN POINTER NEWREC(COUNT);
- EXTERN COUNT OPNFIL(COUNT, TEXT *, COUNT);
- EXTERN COUNT REDREC(COUNT, POINTER, TEXT *);
- EXTERN COUNT RETREC(COUNT, POINTER);
- EXTERN COUNT WRTREC(COUNT, POINTER, TEXT *);
- # else
- static int i_addrec();
- static int i_close_file();
- static int i_commit();
- static int i_delrec();
- static int i_filename();
- static int i_findkey();
- static int i_firstkey();
- static int i_init_file();
- static int i_lastkey();
- static int i_lockrec();
- static int i_login();
- static int i_logoff();
- static int i_nextrec();
- static int i_open_file();
- static int i_prevrec();
- static int i_rereadrec();
- static int i_rollback();
- static int i_selectinx();
- static int i_transact();
- static int i_unlock_rec();
- static int i_updrec();
- static int io_xlate();
- static int add_rec();
- static int cl_ifil();
- static int cre_ifil();
- static int del_rec();
- static int frm_key();
- static int gte_rec();
- static int lst_rec();
- static int nxt_rec();
- static int opn_ifil();
- static int prv_rec();
- static int rrd_rec();
- static int rwt_rec();
- static int create_file();
- static int get_mode();
- static int length_check();
- static int load_keys();
- static int lockit();
- /* externs from C-Tree */
- EXTERN COUNT ADDKEY();
- EXTERN COUNT CLSFIL();
- EXTERN COUNT CREDAT();
- EXTERN COUNT CREIDX();
- EXTERN COUNT CREMEM();
- EXTERN COUNT DELCHK();
- EXTERN POINTER GTEKEY();
- EXTERN POINTER GTKEY();
- EXTERN COUNT INTREE();
- EXTERN COUNT LOKREC();
- EXTERN COUNT LSTKEY();
- EXTERN POINTER LTKEY();
- EXTERN POINTER NEWREC();
- EXTERN COUNT OPNFIL();
- EXTERN COUNT REDREC();
- EXTERN COUNT RETREC();
- EXTERN COUNT WRTREC();
- # endif
-
- /* EXTERNs */
- extern long lseek();
- extern char *alloc();
-
-
- /*
- * C-TREE specific file descriptor structure
- * (index fd_sys will be in parallel with fd[] structure from iogen)
- */
- struct cfd_def
- {
- long cur_recbyt; /* current record offset */
- char *cur_recbuf; /* buffer holding current record */
- int lockflag; /* locking flag */
- long lockbyt; /* offset of locked record */
- char *updbuf; /* pointer to buffer used in update */
- IFIL datafile; /* C-Tree file info */
- IIDX fdkey[MAX_KEYS]; /* C-Tree index/key info */
- };
-
-
- static struct cfd_def cfd[MAX_FILES];
- static int filno_used[MAX_FILES_USED]; /* keep track of file numbers */
-
-
- /*
- *
- * Interface Functions
- *
- */
-
-
- /*
- * Sets up File Name extension, Name is passed in buffer.
- */
- static int i_filename(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- char *f1; /* pointer to filename extension */
-
- if ((f1 = strchr(buffer, '.')) != NULL)
- *f1 = '\0'; /* remove extension from filename */
- return(IOGOOD);
- }
-
-
- /*
- * Initialize C-TREE
- */
- static int i_init_file(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int i;
-
- INTREE(INDEX_BUFFERS, MAX_FILES_USED, NUM_INDEX_SECTS);
-
- for (i = 0; i < MAX_FILES_USED; i++)
- filno_used[i] = FALSE; /* no file numbers in use (yet) */
- return(IOGOOD);
- }
-
- /*
- * C-TREE file open
- */
- static int i_open_file(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat; /* status variable */
- char *datname; /* filename buffer (with .dat) */
- char *idxname; /* filename buffer (with .idx) */
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr; /* pointer to IFIL info */
-
- cptr->cur_recbyt = 0L; /* 0L is actually before first record */
- cptr->cur_recbuf = alloc(fptr->rec_len); /* buffer for current record */
- cptr->lockflag = 0; /* no locks yet */
- cptr->lockbyt = 0L;
-
- dptr = &cptr->datafile; /* pointer to IFIL struct */
- dptr->pfilnam = strsave(fptr->filname); /* fill IFIL struct with info */
- dptr->dfilno = -1; /* no file number (yet) */
- dptr->dreclen = fptr->rec_len; /* set record length */
- dptr->dxtdsiz = fptr->rec_len;
- dptr->dfilmod = get_mode(fptr->openmode); /* get the mode, then the key info */
- dptr->dnumidx = load_keys(fd_sys);
- dptr->ixtdsiz = fptr->rec_len;
- dptr->ifilmod = get_mode(fptr->openmode); /* CHECK THIS!!!!!! */
- dptr->ix = cptr->fdkey; /* point to key info */
- dptr->rfstfld = NULL; /* these two are only needed by R-Tree */
- dptr->rlstfld = NULL;
- dptr->tfilno = -1;
-
- datname = alloc(strlen(fptr->filname) + 5);
- idxname = alloc(strlen(fptr->filname) + 5);
- sprintf(datname, "%s.dat", fptr->filname);
- sprintf(idxname, "%s.idx", fptr->filname);
-
- if (fptr->openmode & OUTPUT_FLAG)
- {
- unlink(datname);
- unlink(idxname);
- }
- free(idxname);
- free(datname);
-
- if (stat = opn_ifil(dptr)) /* open failed */
- {
- if (fptr->openmode & INPUT_FLAG)
- return(io_xlate(fd_sys, stat, "CT OPEN"));
- /* create if update/output mode */
- if (create_file(fd_sys) != IOGOOD)
- return(IOERROR);
- }
- else
- {
- if (length_check(fd_sys) != IOGOOD)
- { /* but the length doesn't match */
- errmsg(FileRecLenChg_s, dptr->pfilnam);
- return(IOERROR);
- }
- }
-
- dptr->dfilno = dptr->tfilno; /* open successful, save file number */
- fptr->exact = 0; /* initialize exact flag */
- return(IOGOOD);
- }
-
- /*
- * Create file(s)
- */
- static int create_file(fd_sys)
- int fd_sys;
- {
- IFIL *dptr = &cfd[fd_sys].datafile; /* point to IFIL info */
- int stat; /* create status */
-
- if (stat = cre_ifil(dptr)) /* create file */
- return(io_xlate(fd_sys, stat, "CT CREATE 1"));
-
- return(IOGOOD); /* s'allright! */
- }
-
- /*
- * Translate Pro-C mode to C-Tree mode
- * - here FairCom's definitions of SHARED & EXCLUSIVE are used!
- */
- static int get_mode(mode)
- int mode;
- {
- if (mode & OUTPUT_FLAG) /* output mode is exclusive */
- return(FIXED | EXCLUSIVE | PERMANENT);
- else /* others are shared */
- return(FIXED | SHARED | PERMANENT);
- }
-
- /*
- * length_check() - check the length of the existing data records
- * - since C-Tree doesn't have a record length check
- * we have to get an int value from byte offset 4
- * in the C-Tree data file header
- */
- extern CTFILE *ct_key; /* extern to ctree's wfils info */
-
- static int length_check(fd_sys)
- int fd_sys;
- {
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
- CTFILE *ct_num; /* pointer for current info */
-
- ct_num = ct_key + dptr->tfilno;
-
- if (ct_num->reclen == dptr->dreclen)
- return(IOGOOD); /* record length OK */
-
- return(IOERROR); /* problem checking record length */
- }
-
- /*
- * Load key information from Pro-C key specifications
- */
- static int load_keys(fd_sys)
- int fd_sys;
- {
- int i, datatype, fldix;
- int nkeys = 0; /* number of keys */
- int dupkeyflag; /* duplicate key flag */
- struct fd_def *fptr = &fd[fd_sys];
- IIDX *kptr = cfd[fd_sys].fdkey; /* pointer to key info */
- ISEG *sptr; /* pointer to segment info */
-
- while (fptr->keys[nkeys].segcount != -1)
- {
- kptr->inumseg = fptr->keys[nkeys].segcount;
- kptr->ikeylen = 0;
- sptr = (ISEG *) alloc(sizeof(ISEG) * fptr->keys[nkeys].segcount);
- kptr->seg = sptr; /* point to segment info */
- kptr->ikeytyp = 0; /* set type to 0 (fixed length key) */
- dupkeyflag = 0; /* initialize flag */
-
- for (i = 0; i < fptr->keys[nkeys].segcount; i++)
- {
- sptr->soffset = fptr->keys[nkeys].segstart[i];
- sptr->slength = fptr->keys[nkeys].seglen[i];
- kptr->ikeylen += fptr->keys[nkeys].seglen[i];
-
- if (fptr->keys[nkeys].keytype == KEY_DUPLICATE)
- dupkeyflag++; /* is it a duplicate? */
-
- fldix = fptr->keys[nkeys].fldindex[i];
- datatype = fptr->flds[fldix].fldtype;
- switch(datatype) /* set segment mode from Pro-C type */
- {
- case CHRTYP:
- sptr->segmode = 0; /* no transformation */
- break;
- case LNGTYP:
- case INTTYP:
- sptr->segmode = 1; /* unsigned integer */
- break;
- case FLTTYP:
- case DBLTYP:
- sptr->segmode = 9; /* floating point */
- break;
- case DATTYP:
- if (fptr->flds[fldix].fldlen == 6)
- sptr->segmode = 0; /* treat as char */
- else
- sptr->segmode = 1; /* treat as int */
- break;
- }
- sptr++; /* next segment */
- }
-
- kptr->inulkey = 0; /* zero for now */
- kptr->iempchr = 0;
- if (dupkeyflag)
- {
- kptr->ikeylen += 4; /* duplicate keys need 4 extra bytes */
- kptr->ikeydup = 1;
- }
- else
- kptr->ikeydup = 0;
-
- kptr++; /* next key */
- nkeys++; /* increment counter */
- }
-
- return(nkeys); /* return number of keys loaded */
- }
-
-
- /*
- * Close data and/or index files and free the fd_def
- */
- static int i_close_file(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat;
- struct cfd_def *cptr = &cfd[fd_sys];
-
- if (stat = cl_ifil(&cptr->datafile))
- return(io_xlate(fd_sys, stat, "CT CLOSE"));
-
- free(cptr->cur_recbuf);
- return(IOGOOD);
- }
-
-
-
- /*
- * Select an index to perform processing on - already done in IOGEN.C
- */
- static int i_selectinx(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- return(IOGOOD);
- }
-
-
- /*
- * Find a record by key value
- * The selectinx function has already set fd[fd_sys].exact to EXACT or PART.
- */
- static int i_findkey(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int keylen; /* length of key */
- int reallen; /* length of key without suffix */
- int keyoff; /* offset of key within buffer */
- int stat; /* status variable */
- char *target; /* pointer to target key buffer */
- char *kcmpbuf; /* buffer for comparing new key */
- struct fd_def *fptr = &fd[fd_sys]; /* pointer to fd_def */
- struct cfd_def *cptr = &cfd[fd_sys]; /* pointer to cfd_def */
- IIDX *kptr; /* pointer to key info */
-
- kptr = &cptr->fdkey[fptr->cur_key]; /* point to current key info */
- keyoff = kptr->seg->soffset; /* get offset, length, etc. */
- keylen = kptr->ikeylen;
- reallen = kptr->seg->slength;
-
- target = alloc(keylen); /* allocate target key buffer */
- frm_key(fd_sys, fptr->cur_key, buffer, target, 0L); /* transform key */
-
- stat = gte_rec(fd_sys, target, buffer); /* get record >= target */
- if (stat)
- {
- free(target);
- return(io_xlate(fd_sys, stat, "CT FIND"));
- }
-
- if (fptr->exact)
- {
- kcmpbuf = alloc(keylen); /* allocate comparison buffer */
- frm_key(fd_sys, fptr->cur_key, buffer, kcmpbuf, 0L);
- /* compare them to see if equal */
- stat = bytecmp(target, kcmpbuf, reallen);
- free(target);
- free(kcmpbuf);
- if (stat)
- return(IONOKEY); /* not equal */
- }
- return(IOGOOD);
- }
-
-
- /*
- * Find first record in the file
- */
- static int i_firstkey(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat; /* gte_rec status */
- char *ptr; /* pointer to key buffer */
- struct fd_def *fptr = &fd[fd_sys]; /* pointer to the fd_def */
- struct cfd_def *cptr = &cfd[fd_sys]; /* pointer to the cfd_def */
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
-
- zerorec(buffer, dptr->dreclen); /* zero buffer and alloc key buffer */
- ptr = alloc(cptr->fdkey[fptr->cur_key].ikeylen);
-
- frm_key(fd_sys, fptr->cur_key, buffer, ptr, 0L);
- stat = gte_rec(fd_sys, ptr, buffer);
- free(ptr); /* inquire on null key and free buffer */
- if (stat)
- return(io_xlate(fd_sys, stat, "CT FIRST"));
-
- return(IOGOOD);
- }
-
-
- /*
- * Find last record in the file using the current key
- */
- static int i_lastkey(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat; /* status variable */
-
- if (stat = lst_rec(fd_sys, buffer))
- {
- if (stat = INOT_ERR)
- return(IOEOF);
-
- return(io_xlate(fd_sys, stat, "CT LAST"));
- }
-
- return(IOGOOD);
- }
-
-
- /*
- * Find next record in the file by current index
- * The IOGEN function will check for EXACT next match
- */
- static int i_nextrec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat;
- long sav_recbyt;
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
-
- sav_recbyt = cptr->cur_recbyt; /* save current record offset */
-
- if (stat = nxt_rec(fd_sys, buffer))
- {
- cptr->cur_recbyt = sav_recbyt; /* restore current record offset */
- if (stat == INOT_ERR)
- return(IOEOF);
- return(io_xlate(fd_sys, stat, "CT NEXT"));
- }
-
- return(IOGOOD);
- }
-
-
- /*
- * Find previous record in the file by current index
- * The IOGEN function will check for EXACT next match
- */
- static int i_prevrec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat;
- long sav_recbyt;
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
-
- sav_recbyt = cptr->cur_recbyt; /* save current record offset */
-
- if (stat = prv_rec(fd_sys, buffer))
- {
- cptr->cur_recbyt = sav_recbyt; /* restore current record offset */
- if (stat == INOT_ERR)
- return(IOTOF);
- return(io_xlate(fd_sys, stat, "CT PREV"));
- }
-
- return(IOGOOD);
- }
-
-
- /*
- * Re-read/reposition record pointer function - if required
- */
- static int i_rereadrec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- return(IOGOOD);
- }
-
-
- /*
- * Add a new record - unlocking is handled from IOGEN
- */
- static int i_addrec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat;
-
- if (stat = add_rec(fd_sys, buffer))
- return(io_xlate(fd_sys, stat, "CT ADD"));
-
- return(IOGOOD);
- }
-
-
- /*
- * Update the current record - unlocking is handled from IOGEN
- */
- static int i_updrec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat;
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile;
-
- cptr->updbuf = alloc(dptr->dreclen); /* allocate temporary buffer */
-
- if (stat = rrd_rec(fd_sys, cptr->updbuf)) /* reread the record */
- {
- free(cptr->updbuf);
- return(io_xlate(fd_sys, stat, "CT UPDT1"));
- }
-
- stat = rwt_rec(fd_sys, buffer);
- free(cptr->updbuf);
- if (stat)
- return(io_xlate(fd_sys, stat, "CT UPDT2"));
-
- return(IOGOOD);
- }
-
-
- /*
- * Delete the current record.
- */
- static int i_delrec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat;
- struct cfd_def *cptr = &cfd[fd_sys];
-
- if (stat = del_rec(fd_sys))
- return(io_xlate(fd_sys, stat, "CT DEL"));
-
- cptr->lockflag = 0;
- cptr->lockbyt = 0L;
- return(IOGOOD);
- }
-
-
- /*
- * Lock Record - dummy function since C-Tree locks automatically
- * - write lock request from lockit() to allow for explicit locking
- * (will return IOGOOD or NO_ERROR (both 0) if no lock wanted)
- */
- static int i_lockrec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- int stat;
- long recbyt;
-
- recbyt = cfd[fd_sys].cur_recbyt;
- if (lockit(fd_sys, recbyt, WLOCKON))
- return(io_xlate(fd_sys, stat, "CT LOCK"));
- return(IOGOOD);
- }
-
- /*
- * Unlock Record
- * - returns with IOGOOD if no locks used
- */
- static int i_unlock_rec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- lockit(fd_sys, cfd[fd_sys].lockbyt, LOCKOFF);
- return(IOGOOD);
- }
-
- /*
- * Login
- */
- static int i_login(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- return(IOGOOD);
- }
-
- /*
- * Logoff
- */
- static int i_logoff(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- return(IOGOOD);
- }
-
- /*
- * End (Commit) transaction
- */
- static int i_commit(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- return(IOGOOD);
- }
-
- /*
- * Rollback transaction
- */
- static int i_rollback(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- return(IOGOOD);
- }
-
- /*
- * Start transaction
- */
- static int i_transact(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- return(IOGOOD);
- }
-
-
- /*
- * This routine translates C-TREE Error codes into PRO-C error codes.
- * If no PRO-C equivalent, displays the error number.
- */
- static int io_xlate(fd_sys, ernum, rtnname)
- int fd_sys;
- int ernum;
- char *rtnname;
- {
- switch(ernum)
- {
- case KCRAT_ERR:
- case DCRAT_ERR:
- return(IONOLOCK);
- case FNOP_ERR:
- return(IOBADOPEN);
- case IPND_ERR:
- case DLOK_ERR:
- return(IOLOCKED);
- case KDUP_ERR:
- return(IODUP);
- case ICUR_ERR:
- case INOT_ERR:
- return(IONOKEY);
- case FNUM_ERR:
- return(IONOFILE);
- #ifndef NO_SERVE
- case ASKY_ERR:
- case ASID_ERR:
- errmsg("C-Tree Server Not Running");
- return(IOERROR);
- #endif
- }
-
- if (fd_sys >= 0)
- errmsg(FileDbgError_sdss, "C-TREE", ernum, fd[fd_sys].filname, rtnname);
- else /* if routines called from generated apps without valid fd_sys */
- errmsg(FileDbgError_sds, "C-TREE", ernum, rtnname);
- return(IOERROR);
- }
-
-
- /*******************************************************************************
- * *
- * Static functions used by io3 functions *
- * *
- *******************************************************************************/
-
- /*
- * lockit() - lock/unlock record
- */
- static int lockit(fd_sys, recbyt, lkmod)
- int fd_sys;
- long recbyt;
- int lkmod;
- {
- int stat; /* lock status */
- int lokmod; /* C-Tree lock mode */
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
-
- if (fd[fd_sys].lockmode == NOLOCK) /* if no locking specified */
- return(NO_ERROR); /* just return without doing anything */
-
- /* get lock mode */
- switch(lkmod)
- {
- case LOCKOFF:
- lokmod = FREE;
- break;
- case WLOCKON:
- lokmod = (fptr->openmode & INPUT_FLAG) ? READREC : ENABLE;
- break;
- case RLOCKON:
- lokmod = READREC;
- break;
- default:
- abort_mess("Invalid lock mode in lockit()...\n");
- exit(-1);
- break;
- }
-
- if (lokmod != FREE)
- { /* when locking */
- if (cptr->lockflag == 1) /* if there's a lock free it */
- if (stat = LOKREC(dptr->dfilno, FREE, cptr->lockbyt))
- return(stat);
- }
- /* attempt lock/free */
- if (stat = LOKREC(dptr->dfilno, lokmod, recbyt))
- return(stat);
-
- if (lokmod == FREE) /* free was successful */
- {
- cptr->lockflag = 0; /* so zero the lock info */
- cptr->lockbyt = 0L;
- }
- else /* lock was successful */
- {
- cptr->lockflag = 1; /* so update lock info */
- cptr->lockbyt = recbyt;
- }
-
- return(NO_ERROR);
- }
-
- /*******************************************************************************
- * *
- * Replacement high level routines (so we have control over locking) *
- * *
- *******************************************************************************/
- /*
- * add_rec() - add a record and it key values to the appropriate file(s)
- */
- static int add_rec(fd_sys, recptr)
- int fd_sys;
- char *recptr;
- {
- long recbyt; /* byte offset of record */
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
- IIDX *kptr; /* pointer for key info */
- int datno = dptr->dfilno; /* base data file number (C-Tree) */
- int keyno; /* 'file' number for key (C-Tree) */
- int i, j; /* counters */
- char *target; /* pointer to target key buffer */
- int stat; /* status variable */
-
- if (!recptr)
- return(DNUL_ERR); /* null record passed in */
- recbyt = NEWREC(datno); /* get offset for new record */
- if (!recbyt)
- return(uerr_cod); /* error getting new record */
- if (lockit(fd_sys, recbyt, WLOCKON))/* lock the new record */
- return(DLOK_ERR);
- if (WRTREC(datno, recbyt, recptr)) /* write the data out */
- return(uerr_cod);
- for(i = 0; i < dptr->dnumidx; i++) /* add each of the keys to the index */
- {
- kptr = &cptr->fdkey[i]; /* point to key info for this key */
- keyno = datno + i + 1; /* key's 'file' number */
- target = alloc(kptr->ikeylen); /* allocate and transform target */
- frm_key(fd_sys, i, recptr, target, recbyt);
- stat = ADDKEY(keyno, target, recbyt, REGADD);
- free(target); /* add the key and free the target */
- if (stat) /* cleanup if there was an error */
- {
- for(j = i - 1; j >= 0; j--)/* rebuild and delete each key that */
- { /* was added up 'til now */
- kptr = &cptr->fdkey[j];
- keyno = datno + j + 1;
- target = alloc(kptr->ikeylen);
- frm_key(fd_sys, j, recptr, target, 0L);
- DELCHK(keyno, target, recbyt);
- free(target);
- }
- RETREC(datno, recbyt); /* return this record for use */
- return(stat);
- }
- }
- cptr->cur_recbyt = recbyt; /* update current record offset */
- bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
- return(NO_ERROR);
- }
-
- /*
- * cre_ifil() - create file according to parameters specified in IFIL structure
- */
- static int cre_ifil(dptr)
- IFIL *dptr;
- {
- int i, j; /* counters */
- IIDX *kptr; /* pointer to key info */
- char *datnam, *idxnam; /* fullnames of data and index files */
- int stat;
-
- kptr = dptr->ix; /* dptr->ix is first key */
-
- datnam = alloc(strlen(dptr->pfilnam) + 5);
- idxnam = alloc(strlen(dptr->pfilnam) + 5);
- sprintf(datnam, "%s.dat", dptr->pfilnam);
- sprintf(idxnam, "%s.idx", dptr->pfilnam);
-
- /* find consecutive filno's */
- for(i = 0; i < (MAX_FILES_USED - dptr->dnumidx); i++)
- {
- for(j = 0; j <= dptr->dnumidx; j++)
- if (filno_used[i + j] == TRUE)
- break;
- if (j > dptr->dnumidx)
- break;
- }
- if (i == (MAX_FILES_USED - dptr->dnumidx))
- return(FUSE_ERR); /* must be out of filno's */
-
- if (stat = CREDAT(i, datnam, dptr->dreclen, dptr->dxtdsiz, dptr->dfilmod))
- return(stat); /* error creating datafile */
-
- if (stat = CREIDX(i + 1, idxnam, kptr->ikeylen, kptr->ikeytyp,
- kptr->ikeydup, dptr->dnumidx - 1, dptr->ixtdsiz, dptr->ifilmod))
- { /* error creating the index file */
- CLSFIL(i, dptr->dfilmod);
- unlink(datnam); /* so close and unlink data file */
- free(datnam);
- free(idxnam);
- return(stat);
- }
-
- for(j = 1; j < dptr->dnumidx; j++) /* add any additional keys */
- {
- kptr++; /* point to next one */
- if(stat = CREMEM(i + 1, kptr->ikeylen, kptr->ikeytyp, kptr->ikeydup, j))
- goto create_recover;
- }
-
- /*
- * This wasn't being done at first so we were getting FUSE_ERR (error # 46)
- * coming back at us...
- */
- for(j = 0; j <= dptr->dnumidx; j++)/* flag the filno's as used */
- filno_used[i + j] = TRUE;
-
- dptr->tfilno = i; /* create successful, save file number */
- free(datnam);
- free(idxnam);
- return(NO_ERROR);
-
- create_recover:
- CLSFIL(i, dptr->dfilmod); /* recover from an error */
- CLSFIL(i + 1, dptr->ifilmod); /* by closing and unlinking files */
- unlink(datnam);
- unlink(idxnam);
- free(datnam);
- free(idxnam);
- return(stat); /* then return the status... */
- }
-
- /*
- * cl_ifil() - close file(s)
- */
- static int cl_ifil(dptr)
- IFIL *dptr;
- {
- int i; /* counter */
-
- if (dptr->dnumidx > 0) /* close .idx file */
- if (CLSFIL(dptr->dfilno + 1, PARTIAL))
- return(uerr_cod);
-
- if (CLSFIL(dptr->dfilno, PARTIAL))
- return(uerr_cod); /* close .dat file */
-
- for(i = 0; i <= dptr->dnumidx; i++)
- filno_used[i + dptr->dfilno] = FALSE;
-
- return(IOGOOD);
- }
-
- /*
- * del_rec() - delete a record
- */
- static int del_rec(fd_sys)
- int fd_sys;
- {
- int i, stat;
- char *tmpbufp; /* pointer to temporary buffer */
- char *target; /* pointer to target key buffer */
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
-
- tmpbufp = cptr->cur_recbuf; /* allocate temporary buffer */
-
- if (!tmpbufp)
- return(ICUR_ERR);
-
- if (dptr->dnumidx > 0) /* any indices must be deleted */
- {
- for(i = 0; i < dptr->dnumidx; i++)
- { /* allocate target key buffer */
- target = alloc(cptr->fdkey[i].ikeylen);
- /* transform and delete key */
- frm_key(fd_sys, i, tmpbufp, target, 0L);
- stat = DELCHK(dptr->dfilno + i + 1, target, cptr->cur_recbyt);
- free(target); /* free target key buffer */
- if (stat)
- return(uerr_cod);
- }
- }
- return(RETREC(dptr->dfilno, cptr->cur_recbyt));
- }
-
- /*
- * frm_key() - low level version of C-Tree's frmkey() function
- */
- #ifdef REVBIN
- #undef REVBIN
- #endif
- #ifdef LOW_HIGH
- #define REVBIN
- #endif
- #ifdef HIGH_LOW
- #ifdef UNIFRMAT
- #define REVBIN
- #endif
- #endif
-
- static int frm_key(fd_sys, keyno, recptr, target, recbyt)
- int fd_sys;
- int keyno;
- char *recptr;
- char *target;
- long recbyt;
- {
- struct cfd_def *cptr = &cfd[fd_sys];
- IIDX *kptr = &cptr->fdkey[keyno];
- ISEG *sptr;
- int i, j, len, slen, mod;
- char *recpos;
-
- sptr = kptr->seg;
- for(i = len = 0; i < kptr->inumseg; i++, sptr++)
- {
- recpos = recptr + sptr->soffset;
- len += (slen = sptr->slength);
- mod = sptr->segmode;
- mod &= SEGMSK;
- switch (mod)
- {
- case REGSEG:
- case SRLSEG:
- #ifndef REVBIN
- case INTSEG:
- #endif
- for(j = 0; j++ < slen; )
- *target++ = *recpos++;
- break;
- #ifdef REVBIN
- case INTSEG:
- recpos += slen;
- for(j = 0; j++ < slen; )
- *target++ = *(--recpos);
- break;
- #endif
- case UREGSEG:
- for(j = 0; j++ < slen; )
- *target++ = toupper(*recpos++);
- break;
- case SGNSEG:
- case FLTSEG:
- #ifdef REVBIN
- target += slen;
- for(j = 0; j++ < slen; )
- *(--target) = *recpos++;
- #else
- bytecpy(target, recpos, slen);
- #endif
- if (*target & 0x0080)
- {
- if (mod == SGNSEG)
- *target &= 0x007f;
- }
- else
- *target |= 0x0080;
- target += slen;
- break;
- default:
- abort_mess("ABORT : Invalid segment mode in frm_key()...\n");
- exit(-1);
- break;
- }
- }
- slen = len;
- if (kptr->ikeydup)
- {
- recpos = (char *)&recbyt;
- len += sizeof(long);
- #ifdef LOW_HIGH
- target += sizeof(long);
- for(j = 0; j < sizeof(long); j++)
- *--target = *recpos++;
- #else
- for(j = 0; j < sizeof(long); j++)
- *target++ = *recpos++;
- #endif
- }
- return(len);
- }
-
- /*
- * gte_rec() - read record with greater than or equal key value
- */
- static int gte_rec(fd_sys, target, recptr)
- int fd_sys;
- char *target;
- char *recptr;
- {
- long recbyt; /* byte offset of record */
- char *keybuf; /* pointer to key buffer */
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
- IIDX *kptr; /* pointer for key info */
-
- if (!recptr) /* NULL record pointer */
- return(DNUL_ERR);
-
- kptr = &cptr->fdkey[fptr->cur_key];/* point to current key info */
- keybuf = alloc(kptr->ikeylen); /* alloc key buffer */
- recbyt = GTEKEY(fptr->cur_key + dptr->dfilno + 1, target, keybuf);
-
- free(keybuf); /* get byte offset and free keybuf */
-
- if (!recbyt) /* match not found means...*/
- {
- if (uerr_cod) /* error, or... */
- return(uerr_cod);
- else /* just not there */
- return(INOT_ERR);
- }
-
- if (lockit(fd_sys, recbyt, RLOCKON))/* lock the record... */
- return(DLOK_ERR);
- /* and read it */
- if (REDREC(dptr->dfilno, recbyt, recptr))
- return(uerr_cod);
-
- cptr->cur_recbyt = recbyt; /* set current record offset */
- bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
- return(NO_ERROR);
- }
-
- /*
- * lst_rec() - get last record
- */
- static int lst_rec(fd_sys, recptr)
- int fd_sys;
- char *recptr;
- {
- long recbyt; /* byte offset of last record */
- char *target; /* pointer to target key buffer */
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
- IIDX *kptr; /* pointer to key info */
-
- if (!recptr) /* NULL record pointer passed in */
- return(DNUL_ERR);
-
- kptr = &cptr->fdkey[fptr->cur_key];/* point to key info */
- target = alloc(kptr->ikeylen); /* allocate target key buffer */
- /* find last key value */
- recbyt = LSTKEY(fptr->cur_key + dptr->dfilno + 1, target);
- free(target); /* free target key buffer */
-
- if (!recbyt)
- {
- if (uerr_cod) /* error getting last key */
- return(uerr_cod);
- else
- return(INOT_ERR); /* no last key */
- }
-
- if (lockit(fd_sys, recbyt, RLOCKON))/* lock the record */
- return(DLOK_ERR);
- /* then read the record */
- if (REDREC(dptr->dfilno, recbyt, recptr))
- return(uerr_cod);
-
- cptr->cur_recbyt = recbyt; /* update current record pointer */
- bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
- return(NO_ERROR);
- }
-
- /*
- * nxt_rec() - get next record
- */
- static int nxt_rec(fd_sys, recptr)
- int fd_sys;
- char *recptr;
- {
- long recbyt; /* byte offset of next record */
- char *oldrecp; /* pointer to buffer for old record */
- char *oldkeyp; /* pointer to buffer for old key */
- char *newkeyp; /* pointer to buffer for new key */
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
- IIDX *kptr; /* pointer for key info */
-
- if (!recptr)
- return(DNUL_ERR); /* NULL record pointer passed in */
-
- kptr = &cptr->fdkey[fptr->cur_key];/* point to current key's info */
-
- oldrecp = cptr->cur_recbuf; /* allocate working buffers */
- oldkeyp = alloc(kptr->ikeylen);
- newkeyp = alloc(kptr->ikeylen);
- /* reread previous record */
- if (!oldrecp)
- return(ICUR_ERR);
- /* transform previous key */
- frm_key(fd_sys, fptr->cur_key, oldrecp, oldkeyp, cptr->cur_recbyt);
- /* get record > previous */
- recbyt = GTKEY(dptr->dfilno + fptr->cur_key + 1, oldkeyp, newkeyp);
-
- free(newkeyp); /* free working buffers */
- free(oldkeyp);
-
- if (!recbyt) /* GTKEY failed for some reason */
- {
- if (uerr_cod) /* error on GTKEY */
- return(uerr_cod);
- else /* end of file */
- return(INOT_ERR);
- }
-
- if (lockit(fd_sys, recbyt, RLOCKON))/* lock the record */
- return(DLOK_ERR);
- /* then read it in */
- if (REDREC(dptr->dfilno, recbyt, recptr))
- return(uerr_cod);
-
- cptr->cur_recbyt = recbyt; /* set current record */
- bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
- return(NO_ERROR);
- }
-
- /*
- * opn_ifil() - open file(s) according to parameters specified in IFIL structure
- */
- static int opn_ifil(dptr)
- IFIL *dptr;
- {
- int i, j; /* counters */
- int stat; /* return status */
- char *fullname; /* for expansion of filename */
-
- /* find consecutive filno's */
- for(i = 0; i < (MAX_FILES_USED - dptr->dnumidx); i++)
- {
- for(j = 0; j <= dptr->dnumidx; j++)
- if (filno_used[i + j] == TRUE)
- break;
- if (j > dptr->dnumidx)
- break;
- }
- if (i == (MAX_FILES_USED - dptr->dnumidx))
- return(FUSE_ERR); /* must be out of filno's */
-
- /* open data file */
- fullname = alloc(strlen(dptr->pfilnam) + 5);
- sprintf(fullname, "%s.dat", dptr->pfilnam);
- if (stat = OPNFIL(i, fullname, dptr->dfilmod))
- {
- free(fullname);
- return(stat);
- }
- /* open index file */
- sprintf(fullname, "%s.idx", dptr->pfilnam);
- if (stat = OPNFIL(i + 1, fullname, dptr->ifilmod))
- {
- CLSFIL(i, dptr->dfilmod); /* open of index failed so close data */
- free(fullname);
- return(stat);
- }
-
- free(fullname);
- for(j = 0; j <= dptr->dnumidx; j++)
- filno_used[i + j] = TRUE; /* opens were succesful, flag filno's */
-
- dptr->tfilno = i; /* OK! (return it in tfilno) */
-
- return(NO_ERROR);
- }
-
- /*
- * prv_rec() - get previous record
- */
- static int prv_rec(fd_sys, recptr)
- int fd_sys;
- char *recptr;
- {
- long recbyt; /* byte offset of next record */
- char *oldrecp; /* pointer to buffer for old record */
- char *oldkeyp; /* pointer to buffer for old key */
- char *newkeyp; /* pointer to buffer for new key */
- struct fd_def *fptr = &fd[fd_sys];
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
- IIDX *kptr; /* pointer for key info */
-
- if (!recptr)
- return(DNUL_ERR); /* NULL record pointer passed in */
-
- kptr = &cptr->fdkey[fptr->cur_key];/* point to current key's info */
-
- oldrecp = cptr->cur_recbuf; /* allocate working buffers */
- oldkeyp = alloc(kptr->ikeylen);
- newkeyp = alloc(kptr->ikeylen);
- /* reread previous record */
- if (!oldrecp)
- return(ICUR_ERR);
- /* transform previous key */
- frm_key(fd_sys, fptr->cur_key, oldrecp, oldkeyp, cptr->cur_recbyt);
- /* get record > previous */
- recbyt = LTKEY(dptr->dfilno + fptr->cur_key + 1, oldkeyp, newkeyp);
-
- free(newkeyp); /* free working buffers */
- free(oldkeyp);
-
- if (!recbyt) /* LTKEY failed for some reason */
- {
- if (uerr_cod) /* error on LTKEY */
- return(uerr_cod);
- else /* end of file */
- return(INOT_ERR);
- }
-
- if (lockit(fd_sys, recbyt, RLOCKON))/* lock the record */
- return(DLOK_ERR);
- /* then read it in */
- if (REDREC(dptr->dfilno, recbyt, recptr))
- return(uerr_cod);
-
- cptr->cur_recbyt = recbyt; /* set current record */
- bytecpy(cptr->cur_recbuf, recptr, dptr->dreclen);
- return(NO_ERROR);
- }
-
- /*
- * rrd_rec() - reread current record
- */
- static int rrd_rec(fd_sys, recptr)
- int fd_sys;
- char *recptr;
- {
- struct cfd_def *cptr = &cfd[fd_sys];
- long recbyt = cptr->cur_recbyt; /* byte offset of current record */
- int datno = cptr->datafile.dfilno; /* datafile number (C-Tree) */
-
- if (!recptr)
- return(DNUL_ERR); /* Null record pointer passed in */
-
- /*
- * This lock is a write lock since rrd_rec() is only used for updates...
- */
- if (lockit(fd_sys, recbyt, WLOCKON))/* lock the record */
- return(DLOK_ERR);
- /* read the record */
- return(REDREC(datno, recbyt, recptr));
- }
-
- /*
- * rwt_rec() - rewrite current record
- */
- static int rwt_rec(fd_sys, recptr)
- int fd_sys;
- char *recptr;
- {
- struct cfd_def *cptr = &cfd[fd_sys];
- IFIL *dptr = &cptr->datafile; /* pointer to IFIL info */
- int i; /* counter */
- char *target; /* target key buffer */
- int stat; /* status variable */
-
- if (!recptr)
- return(DNUL_ERR); /* null record pointer passed in */
-
- for(i = 0; i < dptr->dnumidx; i++) /* update any indices */
- {
- /* first we have to delete the old key */
-
- target = alloc(cptr->fdkey[i].ikeylen);
- /* transform and delete key */
- frm_key(fd_sys, i, cptr->updbuf, target, 0L);
- stat = DELCHK(dptr->dfilno + i + 1, target, cptr->cur_recbyt);
- free(target);
- if (stat)
- return(uerr_cod); /* error deleting key */
-
- /* now we add a new one */
-
- target = alloc(cptr->fdkey[i].ikeylen);
- /* transform and add key */
- frm_key(fd_sys, i, recptr, target, 0L);
- stat = ADDKEY(dptr->dfilno + i + 1, target, cptr->cur_recbyt, REGADD);
- free(target);
- if (stat)
- return(uerr_cod); /* error adding key */
- }
- /* write out the data */
- if (WRTREC(dptr->dfilno, cptr->cur_recbyt, recptr))
- return(uerr_cod);
-
- return(NO_ERROR); /* OK, she be done! */
- }
-
-
- /*
- * Assign section
- */
-
- void assign_IO_CT(dbnum)
- int dbnum;
- {
- Fntab[dbnum - 1][0] = (int(*)())0; /* Empty */
- Fntab[dbnum - 1][1] = i_init_file;
- Fntab[dbnum - 1][2] = i_open_file;
- Fntab[dbnum - 1][3] = i_close_file;
- Fntab[dbnum - 1][4] = i_addrec;
- Fntab[dbnum - 1][5] = i_delrec;
- Fntab[dbnum - 1][6] = i_findkey;
- Fntab[dbnum - 1][7] = i_firstkey;
- Fntab[dbnum - 1][8] = i_lastkey;
- Fntab[dbnum - 1][9] = i_lockrec;
- Fntab[dbnum - 1][10] = i_nextrec;
- Fntab[dbnum - 1][11] = i_prevrec;
- Fntab[dbnum - 1][12] = i_unlock_rec;
- Fntab[dbnum - 1][13] = i_updrec;
- Fntab[dbnum - 1][14] = i_commit;
- Fntab[dbnum - 1][15] = i_login;
- Fntab[dbnum - 1][16] = i_logoff;
- Fntab[dbnum - 1][17] = i_rollback;
- Fntab[dbnum - 1][18] = i_transact;
- Fntab[dbnum - 1][19] = i_selectinx;
- Fntab[dbnum - 1][20] = i_rereadrec;
- Fntab[dbnum - 1][21] = i_filename;
- }
-