home *** CD-ROM | disk | FTP | other *** search
- /***( protree.c )************************************************************
- * Internal PRO-TREE Functions (low level) *
- *****************************************************************************
- * *
- * PRO-TREE v1.10 - Copyright (c) 1988, 1990 Vestronix Inc. *
- * *
- * Features: *
- * - Dynamic leveling *
- * - Free list for data file and each key in the index file *
- * - Single-user or Multi-user with appropriate index file locking *
- * - Single record locking on the data file *
- * *
- * Original : NIG 24-Feb-88, GEO 23-Mar-88, VVA Dec-88 (indexing functs) *
- * Changed : JZ Apr-89 *
- * Changed : BRC 4-Dec-89 (dynamic levels, free space reuse) *
- * *
- ****************************************************************************/
- #include "protree.h"
-
-
- /****************************************************************************
- * PRO-TREE Internal Variable Declatations *
- ****************************************************************************/
- WORD16 PT_filecnt = -1; /* file system initialization file */
- WORD8 *PT_Recbuf; /* alloc'd once to prevent thrashing */
- WORD16 PT_Reclen = 0; /* length of PT_Recbuf */
- WORD8 *PT_Nodebuf; /* alloc'd once to prevent thrashing */
- WORD16 PT_Nodelen = 0; /* length of PT_Nodebuf */
- AFDDEF *PT_fd; /* file descriptor structure */
-
-
- /**************************************
- * checks files and file descriptors *
- **************************************/
- int
- PT_chk_open(fd_sys, function)
- int fd_sys;
- char *function;
- {
- int iostat = IOERROR;
-
- if (PT_filecnt <= 0)
- errmsg("ERROR: PRO-TREE file table not initialized (%s)", function);
-
- else if (fd_sys < 0 || fd_sys >= MAX_FILES ||
- (PT_fd[fd_sys].fd_idx < 0 && PT_fd[fd_sys].fd_idx != -123))
- errmsg("ERROR: bad PRO-TREE fd_sys (%d:[1...%d]) (%s)", fd_sys,
- MAX_FILES, function);
-
- else
- iostat = IOGOOD;
-
- return(iostat);
- }
-
-
- /***************************************************************
- * This function applies the given type of lock to the B-Tree *
- ***************************************************************/
- int
- PT_idxlock(fd_sys, type)
- int fd_sys;
- int type;
- {
- int iostat = IOGOOD;
- #if MAXLOCKS > 0
- AFDDEF *aptr = &PT_fd[fd_sys];
- long len1, len2;
- int i, cycles;
-
- if (aptr->ilocked)
- {
- errmsg("ERROR: There is already a lock in place at %d!",
- aptr->ilocked);
- iostat = IOERROR;
- }
- else
- {
- if (type == FILE_LOCK)
- len1 = MAXLOCKS, len2 = 0;
- else
- len1 = 1, len2 = MAXLOCKS - 1;
-
- /* Suddenly Piggy grabs the conch ... */
- if (lseek(aptr->fd_idx, 0L, FDIR_BEGIN) != 0L)
- iostat = IOIDXSEEK;
- else
- {
- iostat = IOILOCKED;
- for (cycles = 0; !cycles || cycles < MAXLOCKTRYS; cycles++)
- {
- if (lseek(aptr->fd_idx, 0L, FDIR_BEGIN) != 0L)
- {
- iostat = IOIDXSEEK;
- break;
- }
- else if (!LOCK_BLK(aptr->fd_idx, 0L, len1))
- {
- aptr->ilocked = FILE_LOCK;
- iostat = IOGOOD;
- break;
- }
- }
- }
-
- /* ... he speaks his piece ... */
- if (type == READ_LOCK && len2 > 0)
- {
- iostat = IOILOCKED;
- for (cycles = 0; !cycles || cycles < MAXLOCKTRYS; cycles++)
- {
- for (i = 1; i <= len2; i++)
- {
- if (lseek(aptr->fd_idx, (long)i, FDIR_BEGIN) != (long)i)
- {
- iostat = IOIDXSEEK;
- break;
- }
- else if (!LOCK_BLK(aptr->fd_idx, (long)i, 1L))
- {
- aptr->ilocked = i;
- iostat = IOGOOD;
- break;
- }
- }
- if (iostat != IOILOCKED || aptr->ilocked)
- break;
- }
- }
- else if (type == WRITE_LOCK && len2 > 0)
- {
- iostat = IOILOCKED;
- for (cycles = 0; !cycles || cycles < MAXLOCKTRYS; cycles++)
- {
- if (lseek(aptr->fd_idx, 1L, FDIR_BEGIN) != 1L)
- {
- iostat = IOIDXSEEK;
- break;
- }
- else if (!LOCK_BLK(aptr->fd_idx, 1L, len2))
- {
- aptr->ilocked = WRITE_LOCK;
- iostat = IOGOOD;
- break;
- }
- }
- }
-
- /* ... and he gives back the shell. */
- if (type != FILE_LOCK && aptr->ilocked && len2 > 0)
- {
- if (lseek(aptr->fd_idx, 0L, FDIR_BEGIN) != 0L)
- iostat = IOIDXSEEK;
- else if (LOCK_REL(aptr->fd_idx, 0L, len1))
- iostat = IOINOLOCK;
- }
- }
- #endif
-
- return(iostat);
- }
-
-
- /*****************************************************************
- * This function removes the given type of lock from the B-Tree *
- *****************************************************************/
- int
- PT_idxunlock(fd_sys, type)
- int fd_sys;
- int type;
- {
- int iostat = IOGOOD;
- #if MAXLOCKS > 0
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr;
- long pos, len;
- int key, lev;
-
- /* get amnesia when the lock is released */
- if (aptr->ilocked)
- {
- if (aptr->ilocked < 0)
- {
- iostat = PT_flush_cache(fd_sys);
- for (key = 0; key < fptr->key_cnt; key++)
- {
- kptr = &(aptr->keyinfo[key]);
- for (lev = 0; lev < kptr->k_levs; lev++)
- kptr->c_elt[lev] = -1;
- }
- }
-
- if (aptr->ilocked == FILE_LOCK)
- pos = 0L, len = MAXLOCKS;
- else if (aptr->ilocked == WRITE_LOCK)
- pos = 1L, len = MAXLOCKS - 1;
- else if (aptr->ilocked > 0)
- pos = aptr->ilocked, len = 1;
-
- if (lseek(aptr->fd_idx, pos, FDIR_BEGIN) != pos)
- {
- if (iostat == IOGOOD)
- iostat = IOIDXSEEK;
- }
- else if (!LOCK_REL(aptr->fd_idx, pos, len))
- aptr->ilocked = 0;
- else if (iostat == IOGOOD)
- iostat = IOINOLOCK;
- }
- #endif
-
- return(iostat);
- }
-
-
- /*************************************************************************
- * Write out a number, doing any neccessary byte/word/longword swapping *
- *************************************************************************/
- int
- PT_writenum(fd, buf, len)
- int fd;
- char *buf;
- int len;
- {
- int iostat = IOGOOD;
-
- PT_swapper(buf, len);
- if (write(fd, buf, len) != len)
- iostat = IOIDXWRITE;
- PT_swapper(buf, len);
-
- return(iostat);
- }
-
-
- /***********************************************************************
- * Read in a number, doing any neccessary byte/word/longword swapping *
- ***********************************************************************/
- int
- PT_readnum(fd, buf, len)
- int fd;
- char *buf;
- int len;
- {
- int iostat = IOGOOD;
-
- if (read(fd, buf, len) != len)
- iostat = IOIDXREAD;
-
- PT_swapper(buf, len);
-
- return(iostat);
- }
-
-
- /****************************************************************************
- * This bit here does byte/word/longword swapping for binary data types to *
- * get it into Intel form. Since most Intel machines are running DOS the *
- * extra processing overhead is thrust upon the bigger/faster machines. *
- * *
- * NOTE: warnings about unused PARAMETERS or LOCALS should be ignored here *
- ****************************************************************************/
- void
- PT_swapper(buf, len)
- char *buf;
- int len;
- {
- int i, j, tmp;
-
- #ifndef SWAP_WORD8
- for (i = 0; i + 1 < len; i += 2)
- tmp = buf[i], buf[i] = buf[i + 1], buf[i + 1] = tmp;
- #endif /* !SWAP_WORD8 */
-
- #ifndef SWAP_WORD16
- for (i = 0; i + 3 < len; i += 4)
- for (j = 0; j < 2; j++)
- tmp = buf[i + j], buf[i + j] = buf[i + j + 2], buf[i + j + 2] = tmp;
- #endif /* !SWAP_WORD16 */
-
- #ifdef SWAP_WORD32
- for (i = 0; i + 7 < len; i += 8)
- for (j = 0; j < 4; j++)
- tmp = buf[i + j], buf[i + j] = buf[i + j + 4], buf[i + j + 4] = tmp;
- #endif /* SWAP_WORD32 */
- }
-
-
- /*****************************************************************
- * Read a data record, calling PT_swapper() for all numeric fields *
- *****************************************************************/
- int
- PT_readdata(fd_sys, buf)
- int fd_sys;
- char *buf;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- int i, iostat = IOGOOD;
-
- if (aptr->doffset == PTNOPTR)
- iostat = IOERROR;
- else if (lseek(fptr->fd_num, aptr->doffset, FDIR_BEGIN) != aptr->doffset)
- iostat = IODATSEEK;
- else if (read(fptr->fd_num, buf, (int)fptr->rec_len) != fptr->rec_len)
- iostat = IODATREAD;
-
- /* swap any binary data */
- else
- {
- for (i = 0; i < fptr->fld_cnt; i++)
- {
- switch (fptr->flds[i].fldtype)
- {
- case INTTYP: /* two byte integer */
- case LNGTYP: /* four byte integer */
- case FLTTYP: /* single precision FP number (usually 4 long) */
- case DBLTYP: /* double precision FP number (usually 8 long) */
- PT_swapper(&buf[fptr->flds[i].fldstart],
- fptr->flds[i].fldlen);
- break;
- }
- }
- }
-
- return(iostat);
- }
-
-
- /******************************************************************
- * Write a data record, calling PT_swapper() for all numeric fields *
- ******************************************************************/
- int
- PT_writedata(fd_sys, buf)
- int fd_sys;
- char *buf;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- int i, iostat = IOGOOD;
- #ifdef ANSI
- extern int i_lockrec(int, char *);
- #else
- extern int i_lockrec();
- #endif
-
- if (aptr->doffset == PTNOPTR)
- {
- /* try to re-cycle an old node */
- if ((aptr->doffset = PT_recreuse(fd_sys)) == PTNOPTR)
- {
- /* nothing to re-cycle ... carve out a new one */
- do
- {
- aptr->doffset = lseek(fptr->fd_num, 0L, FDIR_EOF);
- }
- while ((iostat = i_lockrec(fd_sys, NULL)) == IOLOCKED);
- }
- }
-
- /* swap any binary data */
- for (i = 0; iostat == IOGOOD && i < fptr->fld_cnt; i++)
- {
- switch (fptr->flds[i].fldtype)
- {
- case INTTYP: /* two byte integer */
- case LNGTYP: /* four byte integer */
- case FLTTYP: /* single precision FP number (usually 4 long) */
- case DBLTYP: /* double precision FP number (usually 8 long) */
- PT_swapper(&buf[fptr->flds[i].fldstart],
- fptr->flds[i].fldlen);
- break;
- }
- }
-
- if (lseek(fptr->fd_num, aptr->doffset, FDIR_BEGIN) != aptr->doffset)
- iostat = IODATSEEK;
- else if (write(fptr->fd_num, buf, (int)fptr->rec_len) != fptr->rec_len)
- iostat = IODATWRITE;
-
- /* swap any binary data back */
- for (i = 0; iostat == IOGOOD && i < fptr->fld_cnt; i++)
- {
- switch (fptr->flds[i].fldtype)
- {
- case INTTYP: /* two byte integer */
- case LNGTYP: /* four byte integer */
- case FLTTYP: /* single precision FP number (usually 4 long) */
- case DBLTYP: /* double precision FP number (usually 8 long) */
- PT_swapper(&buf[fptr->flds[i].fldstart],
- fptr->flds[i].fldlen);
- break;
- }
- }
-
- return(iostat);
- }
-
-
- /****************************************************************************
- * Write a new style header, including PRO-TREE version, number of levels *
- * and elements in the tree, and all field and key information. Old style *
- * files can still be read with this version of PRO-TREE, but it will *
- * complain about them as it cannot glean any critical info from them. *
- ****************************************************************************/
- int
- PT_writehdr(fd_sys)
- int fd_sys; /* file descriptor in PT_fd table */
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- WORD16 b2;
- WORD32 b4;
- int i, key, seg, iostat = IOGOOD;
- char fldname[FIELD_NAME_LEN + 1];
- char version[11];
-
- if (lseek(aptr->fd_idx, 0L, FDIR_BEGIN) != 0L)
- {
- iostat = IOIDXSEEK;
- goto error;
- }
-
- memcpy(version, "PROTREE", 7);
- memcpy(version + 7, aptr->version, 3);
- version[10] = 0;
- if (write(aptr->fd_idx, version, 10) != 10)
- {
- iostat = IOIDXWRITE;
- goto error;
- }
-
- b2 = aptr->maxelts;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
-
- b2 = fptr->rec_len;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
-
- b2 = fptr->fld_cnt;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
-
- b2 = fptr->key_cnt;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
-
- aptr->ddatptr = (WORD32)tell(aptr->fd_idx);
- b4 = PTNOPTR;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b4, 4)) != IOGOOD)
- goto error;
-
- for (i = 0; i < fptr->fld_cnt; i++)
- {
- memset(fldname, 0, FIELD_NAME_LEN + 1);
- strncpy(fldname, fptr->flds[i].fldname, FIELD_NAME_LEN);
- if (write(aptr->fd_idx, fldname, FIELD_NAME_LEN) != FIELD_NAME_LEN)
- {
- iostat = IOIDXWRITE;
- goto error;
- }
- b2 = fptr->flds[i].fldtype;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- b2 = fptr->flds[i].fldstart;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- b2 = fptr->flds[i].fldlen;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- }
-
- for (key = 0; key < fptr->key_cnt; key++)
- {
- for (seg = 0; seg < fptr->keys[key].segcount; seg++)
- {
- b2 = fptr->keys[key].segstart[seg];
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- b2 = fptr->keys[key].seglen[seg];
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- b2 = fptr->keys[key].keytype;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- b2 = fptr->flds[fptr->keys[key].fldindex[seg]].fldtype;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- b2 = seg + 1 == fptr->keys[key].segcount ? 0 : 1;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- }
- b4 = PTNOPTR;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b4, 4)) != IOGOOD)
- goto error;
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b4, 4)) != IOGOOD)
- goto error;
- }
-
- error: /* sorry folks, but this just seemed cleaner than many returns */
-
- if (iostat == IOGOOD)
- iostat = PT_readhdr(fd_sys);
-
- return(iostat);
- }
-
-
- /****************************************************************************
- * Read a PRO-TREE header, including PRO-TREE version, number of levels *
- * and elements in the tree, and all field and key information. Old style *
- * files can still be read with this version of PRO-TREE, but it will *
- * complain about them as it cannot glean any critical info from them. *
- ****************************************************************************/
- int
- PT_readhdr(fd_sys)
- int fd_sys; /* file descriptor in PT_fd table */
- {
- int i, seg, key, levs, segkey, stuff[5], iostat = IOGOOD;
- WORD16 b2;
- WORD32 b4;
- long pos1, pos2;
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr;
- char fldname[FIELD_NAME_LEN + 1];
- char version[11];
-
- if (lseek(aptr->fd_idx, 0L, FDIR_BEGIN) != 0L)
- {
- iostat = IOIDXSEEK;
- goto error;
- }
-
- if (read(aptr->fd_idx, version, 10) != 10)
- {
- iostat = IOIDXREAD;
- goto error;
- }
- memcpy(aptr->version, version + 7, 3);
- aptr->version[3] = 0;
- if (memcmp(version, "PROTREE", 7))
- {
- errmsg("ERROR: %s is not a current PROTREE index!", aptr->iname);
- iostat = IOBADOPEN;
- goto error;
- }
- else if (memcmp(aptr->version, CURRENT_VERSION, 3))
- {
- errmsg("ERROR: PROTREE version mismatch (program:%s != %s:%s)",
- CURRENT_VERSION, aptr->iname, aptr->version);
- iostat = IOBADOPEN;
- goto error;
- }
-
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- aptr->maxelts = b2;
- if (aptr->maxelts < 2)
- {
- errmsg("ERROR: Invalid element count: %d (min is 2) in %s", b2,
- aptr->iname);
- iostat = IOERROR;
- goto error;
- }
-
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if (b2 != fptr->rec_len)
- {
- errmsg("ERROR: %s HDR is %d byte%s too %s", aptr->iname,
- b2 > fptr->rec_len ? b2 - fptr->rec_len : fptr->rec_len - b2,
- b2 == 1 ? "" : "s", b2 > fptr->rec_len ? "long" : "short");
- iostat = IOERROR;
- goto error;
- }
-
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if (b2 != fptr->fld_cnt)
- {
- errmsg("ERROR: Field count change: %s has %d too %s fields",
- aptr->iname,
- b2 > fptr->fld_cnt ? b2 - fptr->fld_cnt : fptr->fld_cnt - b2,
- b2 > fptr->fld_cnt ? "many" : "few");
- iostat = IOFLDDEF;
- goto error;
- }
-
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if (b2 != fptr->key_cnt)
- {
- errmsg("ERROR: Key count change: %s has %d too %s keys", aptr->iname,
- b2 > fptr->key_cnt ? b2 - fptr->key_cnt : fptr->key_cnt - b2,
- b2 > fptr->key_cnt ? "many" : "few");
- iostat = IOKEYDEF;
- goto error;
- }
- aptr->keyinfo = (KINFO *)alloc(sizeof(KINFO) * fptr->key_cnt);
-
- aptr->ddatptr = (WORD32)tell(aptr->fd_idx);
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b4, 4)) != IOGOOD)
- goto error;
-
- for (i = 0; i < fptr->fld_cnt; i++)
- {
- if (read(aptr->fd_idx, fldname, FIELD_NAME_LEN) != FIELD_NAME_LEN)
- {
- iostat = IOIDXREAD;
- goto error;
- }
- fldname[FIELD_NAME_LEN] = 0;
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if (b2 != fptr->flds[i].fldtype)
- {
- errmsg("ERROR: Field %d(%s) type change in %s", i + 1, fldname,
- aptr->iname);
- iostat = IOFLDDEF;
- goto error;
- }
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if (b2 != fptr->flds[i].fldstart)
- {
- errmsg("ERROR: Field %d(%s) offset change in %s", i + 1, fldname,
- aptr->iname);
- iostat = IOFLDDEF;
- goto error;
- }
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if (b2 != fptr->flds[i].fldlen)
- {
- errmsg("ERROR: Field %d(%s) length change in %s", i + 1, fldname,
- aptr->iname);
- iostat = IOFLDDEF;
- goto error;
- }
- }
-
- for (key = 0; key < fptr->key_cnt; key++)
- {
- fptr->cur_key = key;
- kptr = &(aptr->keyinfo[fptr->cur_key]);
- kptr->k_leng = 0;
-
- for (seg = 0; seg < fptr->keys[key].segcount; seg++)
- {
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if ((stuff[0] = b2) != fptr->keys[key].segstart[seg])
- {
- errmsg("ERROR: Offset change in key %d:%d (program:%d %s:%d) (%ld)",
- fptr->cur_key + 1, seg + 1, fptr->keys[key].segstart[seg],
- aptr->iname, (int)b2, (WORD32)tell(aptr->fd_idx));
- iostat = IOKEYDEF;
- goto error;
- }
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if ((stuff[1] = b2) != fptr->keys[key].seglen[seg])
- {
- errmsg("ERROR: Length change in key %d:%d (program:%d %s:%d) (%ld)",
- fptr->cur_key + 1, seg + 1, fptr->keys[key].seglen[seg],
- aptr->iname, (int)b2, (WORD32)tell(aptr->fd_idx));
- iostat = IOKEYDEF;
- goto error;
- }
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if ((stuff[2] = b2) != fptr->keys[key].keytype)
- {
- errmsg("ERROR: Uniquness change in key %d:%d (program:%d %s:%d) (%ld)",
- fptr->cur_key + 1, seg + 1, fptr->keys[key].keytype,
- aptr->iname, (int)b2, (WORD32)tell(aptr->fd_idx));
- iostat = IOKEYDEF;
- goto error;
- }
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if ((stuff[3] = b2) != fptr->flds[fptr->keys[key].fldindex[seg]].fldtype)
- {
- errmsg("ERROR: Type change in key %d:%d (program:%d %s:%d) (%ld)",
- fptr->cur_key + 1, seg + 1,
- fptr->flds[fptr->keys[key].fldindex[seg]].fldtype,
- aptr->iname, (int)b2, (WORD32)tell(aptr->fd_idx));
- iostat = IOKEYDEF;
- goto error;
- }
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b2, 2)) != IOGOOD)
- goto error;
- if ((stuff[4] = b2) != (seg + 1 == fptr->keys[key].segcount ? 0 : 1))
- {
- errmsg("ERROR: Membership change in key %d:%d (program:%d %s:%d) (%ld)",
- fptr->cur_key + 1, seg + 1,
- (seg + 1 == fptr->keys[key].segcount ? 0 : 1),
- aptr->iname, (int)b2, (WORD32)tell(aptr->fd_idx));
- iostat = IOKEYDEF;
- goto error;
- }
-
- kptr->sd[seg].s_recstart = stuff[0]; /* record offset */
- kptr->sd[seg].s_keystart = kptr->k_leng; /* key offset */
- kptr->k_leng += stuff[1]; /* key length */
- kptr->sd[seg].s_leng = stuff[1]; /* segment length */
- if (!stuff[4])
- kptr->k_type = stuff[2]; /* uniq or dup */
- kptr->sd[seg].s_vtyp = stuff[3]; /* key type */
- }
-
- kptr->k_segs = fptr->keys[key].segcount;
-
- /* initialize duplicate segment */
- if (kptr->k_type == KEY_DUPLICATE)
- {
- kptr->sd[DUPSEG].s_keystart = kptr->k_leng;
- kptr->sd[DUPSEG].s_leng = sizeof(WORD32);
- kptr->sd[DUPSEG].s_vtyp = LNGTYP;
- kptr->k_leng += sizeof(WORD32);
- }
-
- /* allocate the top level */
- PT_makenodes(fd_sys, kptr, 1);
-
- kptr->didxptr = (WORD32)tell(aptr->fd_idx);
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b4, 4)) != IOGOOD)
- goto error;
-
- pos1 = (WORD32)tell(aptr->fd_idx);
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b4, 4)) != IOGOOD)
- goto error;
- pos2 = (WORD32)tell(aptr->fd_idx);
- if ((kptr->nodeoffset[0] = b4) == PTNOPTR)
- {
- kptr->nodebuff[0].level = 0;
- if ((iostat = PT_writeidx(fd_sys, 0)) != IOGOOD)
- goto error;
- if (lseek(aptr->fd_idx, pos1, FDIR_BEGIN) != pos1)
- {
- iostat = IOIDXSEEK;
- goto error;
- }
- b4 = kptr->nodeoffset[0];
- if ((iostat = PT_writenum(aptr->fd_idx, (char *)&b4, 4)) != IOGOOD)
- goto error;
- }
- else if ((iostat = PT_readidx(fd_sys, 0, 0)) != IOGOOD)
- goto error;
- if (lseek(aptr->fd_idx, pos2, FDIR_BEGIN) != pos2)
- {
- iostat = IOIDXSEEK;
- goto error;
- }
-
- if (kptr->nodebuff[0].level > 0)
- {
- levs = kptr->nodebuff[0].level + 1;
- kptr->k_levs = -1;
- if ((iostat = PT_resize(fd_sys, kptr, levs)) != IOGOOD)
- goto error;
- }
- }
- fptr->cur_key = 0;
-
- error: /* sorry folks, but this just seemed cleaner than many returns */
-
- return(iostat);
- }
-
-
- /****************************************************************************
- * performs lseek and reads an index node to given buffer by record offset *
- ****************************************************************************/
- int
- PT_readidx(fd_sys, lev, elt)
- int fd_sys;
- int lev;
- int elt;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- long offset;
- int i, j, len, iostat = IOGOOD;
- char *ptr, *ptr2;
-
- if (lev < 0 || lev > kptr->nodebuff[0].level)
- abort_mess("\rDIAG: readidx( lev=%d ) [0..%d]\r\n", lev,
- kptr->nodebuff[0].level);
- else if (lev > 0 && (elt < 0 || elt >= kptr->nodebuff[lev - 1].num_used))
- abort_mess("\rDIAG: readidx( elt=%d ) [0..%d]\r\n", elt,
- kptr->nodebuff[lev - 1].num_used);
-
- if (lev > 0)
- offset = kptr->nodebuff[lev - 1].elt[elt].offset;
- else
- offset = kptr->nodeoffset[0];
-
- if (offset <= 0L)
- abort_mess("\rDIAG: readidx( offset=%ld )\r\n", offset);
-
- /* investigate the need to save current node and/or load a new one */
- if (kptr->c_elt[lev] >= 0)
- {
- if (!lev || (lev > 0 && elt == kptr->c_elt[lev - 1] &&
- kptr->nodeoffset[lev] == offset))
- return(iostat);
- else
- iostat = PT_flush_node(fd_sys, lev);
- }
- kptr->nodeoffset[lev] = offset;
-
- if (lseek(aptr->fd_idx, kptr->nodeoffset[lev], FDIR_BEGIN) !=
- kptr->nodeoffset[lev])
- iostat = IOIDXSEEK;
-
- else
- {
- /* resize the node buffer if need be */
- len = sizeof(WORD16) * 2;
- len += aptr->maxelts * (sizeof(WORD32) + kptr->k_leng);
-
- if (len > PT_Nodelen)
- {
- if (PT_Nodelen > 0)
- free(PT_Nodebuf);
- PT_Nodebuf = alloc(PT_Nodelen = len);
- }
- ptr = PT_Nodebuf;
-
- /* read in the whole chunk */
- if ((j = read(aptr->fd_idx, PT_Nodebuf, len)) != len)
- iostat = IOIDXREAD;
-
- PT_swapper(ptr, sizeof(WORD16));
- memcpy((char *)&(kptr->nodebuff[lev].level), ptr, sizeof(WORD16));
- ptr += sizeof(WORD16);
-
- PT_swapper(ptr, sizeof(WORD16));
- memcpy((char *)&(kptr->nodebuff[lev].num_used), ptr, sizeof(WORD16));
- ptr += sizeof(WORD16);
-
- for (i = 0; i < aptr->maxelts; i++)
- {
- PT_swapper(ptr, sizeof(WORD32));
- memcpy((char *)&(kptr->nodebuff[lev].elt[i].offset), ptr,
- sizeof(WORD32));
- ptr += sizeof(WORD32);
-
- ptr2 = ptr;
- for (j = 0; j < kptr->k_segs; j++)
- {
- switch (kptr->sd[j].s_vtyp)
- {
- case INTTYP: /* two byte integer */
- case LNGTYP: /* four byte integer */
- case FLTTYP: /* single precision FP number (usually 4 long) */
- case DBLTYP: /* double precision FP number (usually 8 long) */
- PT_swapper(ptr, kptr->sd[j].s_leng);
- break;
- }
- ptr += kptr->sd[j].s_leng;
- }
- if (kptr->k_type == KEY_DUPLICATE)
- {
- PT_swapper(ptr, kptr->sd[DUPSEG].s_leng);
- ptr += kptr->sd[DUPSEG].s_leng;
- }
- memcpy(kptr->nodebuff[lev].elt[i].keyval, ptr2, kptr->k_leng);
- }
-
- if (lev > 0)
- kptr->c_elt[lev - 1] = elt;
- kptr->c_elt[lev] = aptr->maxelts + 1;
- }
-
- return(iostat);
- }
-
-
- /*************************************************************************
- * performs lseek and writes an index node to the file by record offset *
- *************************************************************************/
- int
- PT_writeidx(fd_sys, lev)
- int fd_sys;
- int lev;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int i, j;
- char *ptr;
- int iostat = IOGOOD;
- int len;
-
- if (lev < 0 || lev > kptr->k_levs)
- abort_mess("\rDIAG: writeidx( lev=%d ) [0..%d]\r\n", lev, kptr->k_levs);
-
- if (kptr->nodeoffset[lev] == PTNOPTR)
- {
- /* try to re-cycle an old node */
- if ((kptr->nodeoffset[lev] = PT_keyreuse(fd_sys)) == PTNOPTR)
- {
- /* nothing to re-cycle ... carve out a new one */
- kptr->nodeoffset[lev] = lseek(PT_fd[fd_sys].fd_idx, 0L, FDIR_EOF);
- if (kptr->nodeoffset[lev] < 0L)
- iostat = IOIDXSEEK;
-
- /* grab the spot 'cause it may get shared otherwise */
- kptr->changes[lev] = FLUSH_LEVEL;
- }
- else
- kptr->changes[lev] = 0;
- }
-
- if (++kptr->changes[lev] < FLUSH_LEVEL)
- return(iostat);
-
- if (iostat == IOGOOD &&
- lseek(aptr->fd_idx, kptr->nodeoffset[lev], FDIR_BEGIN) !=
- kptr->nodeoffset[lev])
- iostat = IOIDXSEEK;
-
- else if (iostat == IOGOOD)
- {
- /* resize the node buffer if need be */
- len = sizeof(WORD16) * 2;
- len += aptr->maxelts * (sizeof(WORD32) + kptr->k_leng);
-
- if (len > PT_Nodelen)
- {
- if (PT_Nodelen > 0)
- free(PT_Nodebuf);
- PT_Nodebuf = alloc(PT_Nodelen = len);
- }
- ptr = PT_Nodebuf;
-
- memcpy(ptr, (char *)&(kptr->nodebuff[lev].level), sizeof(WORD16));
- PT_swapper(ptr, sizeof(WORD16));
- ptr += sizeof(WORD16);
-
- memcpy(ptr, (char *)&(kptr->nodebuff[lev].num_used), sizeof(WORD16));
- PT_swapper(ptr, sizeof(WORD16));
- ptr += sizeof(WORD16);
-
- for (i = 0; i < aptr->maxelts; i++)
- {
- memcpy(ptr, (char *)&(kptr->nodebuff[lev].elt[i].offset),
- sizeof(WORD32));
- PT_swapper(ptr, sizeof(WORD32));
- ptr += sizeof(WORD32);
-
- if (!kptr->nodebuff[lev].elt[i].keyval)
- {
- memset(ptr, 0, kptr->k_leng);
- continue;
- }
-
- memcpy(ptr, kptr->nodebuff[lev].elt[i].keyval, kptr->k_leng);
- for (j = 0; j < kptr->k_segs; j++)
- {
- switch (kptr->sd[j].s_vtyp)
- {
- case INTTYP: /* two byte integer */
- case LNGTYP: /* four byte integer */
- case FLTTYP: /* single precision FP number (usually 4 long) */
- case DBLTYP: /* double precision FP number (usually 8 long) */
- PT_swapper(ptr, kptr->sd[j].s_leng);
- break;
- }
- ptr += kptr->sd[j].s_leng;
- }
- if (kptr->k_type == KEY_DUPLICATE)
- {
- PT_swapper(ptr, kptr->sd[DUPSEG].s_leng);
- ptr += kptr->sd[DUPSEG].s_leng;
- }
- }
-
- if (write(aptr->fd_idx, PT_Nodebuf, len) != len)
- iostat = IOIDXWRITE;
- }
-
- kptr->changes[lev] = 0;
- if (kptr->c_elt[lev] < 0)
- kptr->c_elt[lev] = aptr->maxelts + 1;
-
- return(iostat);
- }
-
-
- #ifndef INCREMENTAL_DUP_VALUES
- /****************************************************************
- * set up a key whose last segment contains the next available *
- * suffix in the sequence for exact match to the target key *
- ****************************************************************/
- int
- PT_new_dup(fd_sys, keyval)
- int fd_sys;
- char *keyval;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- WORD32 dupnum;
- int iostat = IOGOOD;
-
- dupnum = aptr->doffset;
- memcpy(keyval + kptr->sd[DUPSEG].s_keystart, (char *)&dupnum,
- kptr->sd[DUPSEG].s_leng);
-
- return(iostat);
- }
- #endif
-
-
- #ifdef INCREMENTAL_DUP_VALUES
- /****************************************************************
- * set up a key whose last segment contains the next available *
- * suffix in the sequence for exact match to the target key *
- ****************************************************************/
- int
- PT_new_dup(fd_sys, keyval)
- int fd_sys;
- char *keyval;
- {
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- char *tmpkey;
- WORD32 dupnum;
- int lev, elt, iostat = IOGOOD;
-
- /* prepare a key with the highest possible duplicate segment */
- tmpkey = alloc(kptr->k_leng);
- memcpy(tmpkey, keyval, kptr->k_leng);
- dupnum = 0x7fffffff;
- memcpy(tmpkey + kptr->sd[DUPSEG].s_keystart, (char *)&dupnum,
- kptr->sd[DUPSEG].s_leng);
-
- dupnum = 0L;
-
- if (PT_gteq_key(fd_sys, tmpkey, TRUE) != PTNOPTR)
- iostat = IONOKEY;
- else if (PT_prev_key(fd_sys) != PTNOPTR)
- {
- lev = kptr->nodebuff[0].level;
- elt = kptr->c_elt[lev];
- if (!PT_keycmp(fd_sys, keyval, kptr->nodebuff[lev].elt[elt].keyval,
- KEY_UNIQUE))
- memcpy((char *)&dupnum, kptr->nodebuff[lev].elt[elt].keyval +
- kptr->sd[DUPSEG].s_keystart, kptr->sd[DUPSEG].s_leng);
- }
-
- dupnum++;
- memcpy(keyval + kptr->sd[DUPSEG].s_keystart, (char *)&dupnum,
- kptr->sd[DUPSEG].s_leng);
-
- free(tmpkey);
-
- return(iostat);
- }
- #endif
-
-
- /************************************************************************
- * Primary function for adding new key to a B-tree index. Keys larger *
- * or smaller than any on file are trapped for special handling, *
- * otherwise falls through to normal keyadd function *
- ************************************************************************/
- int
- PT_add_key(fd_sys, keyval)
- int fd_sys;
- char *keyval;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int n, lev, iostat = IOGOOD;
- char *kval;
-
- kval = alloc(kptr->k_leng);
- memcpy(kval, keyval, kptr->k_leng);
-
- if (PT_gteq_key(fd_sys, kval, TRUE) != PTNOPTR)
- iostat = IODUP;
- else
- {
- lev = kptr->nodebuff[0].level;
-
- /* empty tree case */
- if (!lev && !kptr->nodebuff[0].num_used)
- kptr->c_elt[0] = 0;
-
- n = kptr->nodebuff[lev].level;
- if (n < 0 || n >= kptr->k_levs)
- abort_mess("\rDIAG: add_key( level[%d]=%d ) [0..%d]\r\n",
- lev, kptr->nodebuff[lev].level, kptr->k_levs);
- iostat = PT_add_elt(fd_sys, lev, aptr->doffset, kval);
- lev = kptr->nodebuff[n].level;
- }
-
- /* inform ancestors of maximum keys */
- while (iostat == IOGOOD && lev > 0)
- {
- if (kptr->c_elt[lev] + 1 == kptr->nodebuff[lev].num_used)
- {
- lev--;
- memcpy(kptr->nodebuff[lev].elt[kptr->c_elt[lev]].keyval, kval,
- kptr->k_leng);
- iostat = PT_writeidx(fd_sys, lev);
- }
- else
- break;
- }
-
- free(kval);
-
- return(iostat);
- }
-
-
- int
- PT_add_elt(fd_sys, lev, offset, keyval)
- int fd_sys;
- int lev;
- long offset;
- char *keyval;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- BNODE *node;
- char *kval;
- int elt, i, iostat = IOGOOD;
-
- kval = alloc(kptr->k_leng);
- memcpy(kval, keyval, kptr->k_leng);
-
- if (lev < 0)
- abort_mess("\rDIAG: add_elt( lev=%d )\r\n", lev);
-
- elt = kptr->c_elt[lev];
- if (elt < 0 || elt > aptr->maxelts)
- abort_mess("\rDIAG: add_elt( c_elt[%d]=%d ) [0..%d]\r\n", lev, elt,
- aptr->maxelts);
-
- if (kptr->nodebuff[lev].num_used < 0)
- abort_mess("\rDIAG: add_elt( num_used[%d]=%d )\r\n", lev,
- kptr->nodebuff[lev].num_used);
- else if (kptr->nodebuff[lev].num_used == aptr->maxelts)
- iostat = PT_add_node(fd_sys, lev, offset, kval);
- else
- {
- /* higher elts up by one */
- node = &(kptr->nodebuff[lev]);
- for (i = node->num_used; i > elt; i--)
- PT_cpyelt(&(node->elt[i]), &(node->elt[i - 1]), kptr->k_leng);
- node->elt[elt].offset = offset;
- memcpy(node->elt[elt].keyval, kval, kptr->k_leng);
- node->num_used++;
-
- iostat = PT_writeidx(fd_sys, lev);
- }
-
- free(kval);
-
- return(iostat);
- }
-
-
- /*****************************************************************************
- * - add a new btree node to the index file
- * - toffset will contain the offset of the new node in the index file, and
- * this value is used on return to become the offset in its parent element
- ******************************************************************************/
- int
- PT_add_node(fd_sys, lev, offset, keyval)
- int fd_sys;
- int lev;
- long offset;
- char *keyval;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- KINFO *ktmp;
- BNODE *node_c, *node_t;
- int n, i, where, left, right, iostat = IOGOOD;
- long ltmp;
- char *kval;
-
- kval = alloc(kptr->k_leng);
- memcpy(kval, keyval, kptr->k_leng);
-
- if (kptr->nodebuff[lev].num_used != aptr->maxelts)
- abort_mess(
- "\rDIAG: add_node( num_used[%d]=%d ) [0..%d] split unneeded\r\n",
- lev, kptr->nodebuff[lev].num_used, aptr->maxelts);
-
- if (kptr->c_elt[lev] > aptr->maxelts)
- abort_mess("\rDIAG: add_node( c_elt[%d]=%d ) node marked unused\r\n",
- lev, kptr->c_elt[lev]);
-
- /* make sure we are not orphans here */
- if (lev == 0)
- {
- iostat = PT_resize(fd_sys, kptr, kptr->nodebuff[0].level + 2);
- lev++;
- }
-
- where = 0;
- for (i = lev; i >= 0; i--)
- {
- if (kptr->c_elt[i] < 0)
- {
- where = 0;
- break;
- }
- else if (kptr->c_elt[i] == 0 && where != 1)
- where = 2;
- else
- {
- n = kptr->nodebuff[i].num_used - 1;
- if (kptr->c_elt[i] + 1 >= kptr->nodebuff[i].num_used &&
- where != 2 && PT_keycmp(fd_sys, kval,
- kptr->nodebuff[i].elt[n].keyval, kptr->k_type) > 0)
- where = 1;
- else
- {
- where = 3;
- break;
- }
- }
- }
-
- if (where == 1)
- {
- /* empty the node and save it as a new one */
- iostat = PT_flush_node(fd_sys, lev);
- PT_zeronode(fd_sys, &(kptr->nodebuff[lev]));
- kptr->nodeoffset[lev] = PTNOPTR;
- kptr->c_elt[lev] = 0;
- iostat = PT_add_elt(fd_sys, lev, offset, kval);
-
- /* add new element to the level above */
- if (lev > 0)
- kptr->c_elt[lev - 1]++;
- n = kptr->nodebuff[lev].level;
- iostat = PT_add_elt(fd_sys, lev - 1, kptr->nodeoffset[lev], kval);
- lev = kptr->nodebuff[n].level;
- }
- else if (where == 2)
- {
- /* empty the node and save it as a new one */
- iostat = PT_flush_node(fd_sys, lev);
- PT_zeronode(fd_sys, &(kptr->nodebuff[lev]));
- kptr->nodeoffset[lev] = PTNOPTR;
- kptr->c_elt[lev] = 0;
- iostat = PT_add_elt(fd_sys, lev, offset, kval);
-
- /* add new element to the level above */
- n = kptr->nodebuff[lev].level;
- iostat = PT_add_elt(fd_sys, lev - 1, kptr->nodeoffset[lev], kval);
- lev = kptr->nodebuff[n].level;
- }
- else if (where == 3)
- {
- right = (left = kptr->nodebuff[lev].num_used) / 2;
- left -= right;
-
- if (kptr->c_elt[lev] < left && left > right)
- left--, right++;
-
- /* save the old arrays and their contents */
- ktmp = (KINFO *)alloc(sizeof(KINFO));
- ktmp->k_leng = kptr->k_leng;
- ktmp->k_type = kptr->k_type;
- ktmp->k_segs = kptr->k_segs;
- for (i = 0; i <= MAXSEGS; i++)
- ktmp->sd[i] = kptr->sd[i];
- PT_makenodes(fd_sys, ktmp, 1);
- PT_zeronode(fd_sys, &(ktmp->nodebuff[0]));
-
- node_t = &(ktmp->nodebuff[0]);
- node_c = &(kptr->nodebuff[lev]);
-
- if (kptr->c_elt[lev] < left || (kptr->c_elt[lev] == left &&
- left < right))
- {
- /* save away the left half of the node and offset */
- for (i = 0; i < left; i++)
- PT_cpyelt(&(node_t->elt[i]), &(node_c->elt[i]), kptr->k_leng);
-
- /* shuffle the right half to the top */
- for (i = 0; i < aptr->maxelts; i++)
- {
- if (i < right)
- PT_cpyelt(&(node_c->elt[i]), &(node_c->elt[i + left]),
- kptr->k_leng);
- else
- PT_zeroelt(fd_sys, &(node_c->elt[i]));
- }
- kptr->nodebuff[lev].num_used = right;
-
- /* write out the right node to disk */
- iostat = PT_writeidx(fd_sys, lev);
- iostat = PT_flush_node(fd_sys, lev);
-
- /* ... and the left node makes the tag ... */
- for (i = 0; i < left || i < right; i++)
- {
- if (i < left)
- PT_cpyelt(&(node_c->elt[i]), &(node_t->elt[i]), kptr->k_leng);
- else
- PT_zeroelt(fd_sys, &(node_c->elt[i]));
- }
- kptr->nodebuff[lev].num_used = left;
- kptr->nodeoffset[lev] = PTNOPTR;
- iostat = PT_add_elt(fd_sys, lev, offset, kval);
-
- /* pappa's got a baby boy! */
- n = kptr->nodebuff[lev].level;
- iostat = PT_add_elt(fd_sys, lev - 1, kptr->nodeoffset[lev],
- node_c->elt[node_c->num_used - 1].keyval);
- lev = kptr->nodebuff[n].level;
- }
- else
- {
- /* save away the right half of the node and offset */
- for (i = 0; i < aptr->maxelts; i++)
- {
- if (i < right)
- PT_cpyelt(&(node_t->elt[i]), &(node_c->elt[i + left]),
- kptr->k_leng);
- if (i >= left)
- PT_zeroelt(fd_sys, &(node_c->elt[i]));
- }
- kptr->nodebuff[lev].num_used = left;
-
- /* flush the new left node to disk */
- ltmp = kptr->nodeoffset[lev];
- kptr->nodeoffset[lev] = PTNOPTR;
- iostat = PT_writeidx(fd_sys, lev);
- iostat = PT_flush_node(fd_sys, lev);
-
- /* pappa's got a baby boy! */
- n = kptr->nodebuff[lev].level;
- iostat = PT_add_elt(fd_sys, lev - 1, kptr->nodeoffset[lev],
- node_c->elt[left - 1].keyval);
- lev = kptr->nodebuff[n].level;
-
- /* do this in case level has changed */
- node_c = &(kptr->nodebuff[lev]);
-
- /* ... and the right node makes the tag ... */
- for (i = 0; i < left || i < right; i++)
- {
- if (i < right)
- PT_cpyelt(&(node_c->elt[i]), &(node_t->elt[i]), kptr->k_leng);
- else
- PT_zeroelt(fd_sys, &(node_c->elt[i]));
- }
- kptr->nodeoffset[lev] = ltmp;
- kptr->c_elt[lev - 1]++;
- kptr->nodebuff[lev].num_used = right;
- kptr->c_elt[lev] -= left;
- iostat = PT_add_elt(fd_sys, lev, offset, kval);
- }
-
- PT_freenodes(fd_sys, ktmp);
- free(ktmp);
- }
-
- free(kval);
-
- return(iostat);
- }
-
-
- /*****************************************************************************
- * - locate the element and empty it, adjusting node if needed
- * - in the case of duplicate keys, the data record offset value
- * (fptr->offset at leaf level) is compared to the value in the index
- * element, and must match to indicate that the correct duplicate key
- * occurrence is the one removed from the index
- */
- int
- PT_del_key(fd_sys, keyval)
- int fd_sys;
- char *keyval;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int iostat;
-
- if (kptr->keyval && PT_gteq_key(fd_sys, kptr->keyval, TRUE) == PTNOPTR)
- iostat = IONOKEY;
- else
- iostat = PT_del_elt(fd_sys, kptr->nodebuff[0].level);
-
- return(iostat);
- }
-
- /*****************************************************************************
- * - blank out element to be removed from index and adjust nodes
- * - if the element to be deleted will create an empty node, its
- * offset is assigned to another element in the parent node if possible,
- * to avoid having the index contain too many unreachable nodes
- * - if removed element was a link to the leaf level, the highest key element
- * remaining in the leaf node is promoted to become the new link
- */
- int
- PT_del_elt(fd_sys, lev)
- int fd_sys;
- int lev;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- BNODE *node = &(kptr->nodebuff[lev]);
- int iostat, i;
- char *keyval;
-
- if (node->num_used <= 0)
- abort_mess("\rDIAG: del_elt( num_used[%d]=%d )\r\n", lev,
- node->num_used);
- else if (lev > 0 && node->num_used == 1)
- iostat = PT_del_node(fd_sys, lev);
- else
- {
- /* higher elts down by one */
- node = &(kptr->nodebuff[lev]);
- for (i = kptr->c_elt[lev] + 1; i < node->num_used; i++)
- PT_cpyelt(&(node->elt[i - 1]), &(node->elt[i]), kptr->k_leng);
- PT_zeroelt(fd_sys, &(node->elt[node->num_used - 1]));
- node->num_used--;
- iostat = PT_writeidx(fd_sys, lev);
-
- if (kptr->c_elt[lev] > 0)
- {
- keyval = node->elt[--kptr->c_elt[lev]].keyval;
- while (iostat == IOGOOD && lev > 0 &&
- kptr->c_elt[lev] + 1 == kptr->nodebuff[lev].num_used)
- {
- lev--;
- memcpy(kptr->nodebuff[lev].elt[kptr->c_elt[lev]].keyval,
- keyval, kptr->k_leng);
- iostat = PT_writeidx(fd_sys, lev);
- }
- }
-
- while (iostat == IOGOOD && !lev && kptr->nodebuff[0].num_used == 1)
- {
- if (kptr->nodebuff[0].level <= 0)
- break;
- else if (PT_first_key(fd_sys) != PTNOPTR)
- iostat = PT_resize(fd_sys, kptr, kptr->nodebuff[0].level);
- else
- iostat = IOERROR;
- }
- }
-
- return(iostat);
- }
-
-
- int
- PT_del_node(fd_sys, lev)
- int fd_sys;
- int lev;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int iostat = IOGOOD;
-
- if (lev < 0)
- abort_mess("\rDIAG: del_node( lev=%d )\r\n", lev);
- else if (lev > 0)
- {
- iostat = PT_keyrecycle(fd_sys, kptr->nodeoffset[lev]);
-
- PT_zeronode(fd_sys, &(kptr->nodebuff[lev]));
- kptr->nodebuff[lev].level = -211;
- kptr->nodebuff[lev].num_used = -212;
- kptr->c_elt[lev] = -213;
- kptr->nodeoffset[lev] = PTNOPTR;
-
- if (iostat == IOGOOD)
- iostat = PT_del_elt(fd_sys, lev - 1);
- }
-
- return(iostat);
- }
-
-
- /***************************************************************************
- * New B-tree indexing functions for IO8.C *
- ****************************************************************************
- *
- * Terminology:
- *
- * node: an array of MAXELTS index key elements
- * element: an element in node containing one key (divided into
- * segments), and record offset (if leaf node), or node
- * offset (otherwise)
- * record offset: byte offset from origin in data file of a record
- * node offset: byte offset in index file of child node to the element
- *
- * level 1: the root node of the index tree, containing MAXELTS elements
- * each with a cnode_offset pointer to a level 2 node
- * level 2: middle level nodes, each containing MAXELTS elements in turn,
- * each with a cnode_offset pointer to a level 3 node
- * level 3: bottom level nodes, each containing MAXELTS elements, each
- * with the record offset (no further levels)
- *
- * The capacity of the index tree is MAXELTS * MAXELTS * MAXELTS keys;
- * however, there will usually be vacant elements in each node, so that the
- * practical capacity might be about half of this.
- *
- * The tree is filled from the bottom up, with elements being placed in the
- * root or middle nodes only when they are first created, or when a node
- * on the next lower level is split: this attains a certain degree of self-
- * adjustment while keeping the number of activated nodes in the index as
- * low as possible.
- *
- * For keys added in random order (that is, neither higher nor lower than
- * all others already on file), bottom and mid level nodes are split when
- * they become full, and the new key added to the newly adjusted tree.
- *
- * If the new key is greater than any other already in the index, as happens
- * with auto-incrementing numerical keys, it will replace the former maximum
- * key in its rootnode position, and at levels further down; however,
- * when lower nodes are filled they are not split, rather, the element is
- * added at the end of the next level up, ensuring that the lower nodes are
- * completely filled before using up higher levels.
- *
- * If the new key is smaller than any other already in the index, it will
- * always go to a child node if possible; if a lower level is filled, the
- * new minimum key will be added to the beginning of the next node up and to
- * the child nodes created from it, rather than split the lower node.
- *
- ***************************************************************************/
-
-
- /**************************************************
- * locates the node element which is equal to or *
- * greater than the key -- returns -1, 0, 1 *
- **************************************************/
- int
- PT_find_match(fd_sys, keyval, t_node, nodepos)
- int fd_sys;
- char *keyval;
- BNODE *t_node;
- int *nodepos;
- {
- int hi, lo, mid, cmp;
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int type = kptr->k_type;
-
- lo = 0;
- hi = t_node->num_used;
-
- /* usual case - more than one key in node */
- while (hi - lo > 1)
- {
- mid = (hi + lo) / 2;
- cmp = PT_keycmp(fd_sys, keyval, t_node->elt[mid].keyval, type);
- if (cmp > 0)
- lo = mid;
- else if (cmp < 0)
- hi = mid;
- else
- lo = hi = mid;
- }
-
- cmp = PT_keycmp(fd_sys, keyval, t_node->elt[lo].keyval, type);
- *nodepos = (cmp <= 0) ? lo : hi;
- if (*nodepos < t_node->num_used)
- cmp = PT_keycmp(fd_sys, keyval, t_node->elt[*nodepos].keyval, type);
- else
- cmp = 1; /* greater than */
-
- return(cmp);
- }
-
-
- /*****************************************************************
- * compare two keys dependent on their type -- returns -1, 0, 1 *
- *****************************************************************/
- int
- PT_keycmp(fd_sys, keyval1, keyval2, mode)
- int fd_sys;
- char *keyval1;
- char *keyval2;
- int mode;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- WORD16 b2_1, b2_2;
- WORD32 b4_1, b4_2;
- FLOAT32 ftmp1, ftmp2;
- FLOAT64 dtmp1, dtmp2;
- WORD32 dupnum1, dupnum2;
- int i, iostat;
-
- /* for each segment */
- for (iostat = i = 0; !iostat && i < kptr->k_segs; i++)
- {
- /* compare the segments according to type */
- switch (kptr->sd[i].s_vtyp)
- {
- case CHRTYP :
- case LOGTYP :
- case MEMTYP :
- case DATTYP :
- iostat = memcmp(keyval1 + kptr->sd[i].s_keystart,
- keyval2 + kptr->sd[i].s_keystart, kptr->sd[i].s_leng);
- break;
-
- case INTTYP: /* two byte integer */
- case LNGTYP: /* four byte integer */
- if (kptr->sd[i].s_leng == 2)
- {
- memcpy((char *)&b2_1, keyval1 + kptr->sd[i].s_keystart,
- sizeof(b2_1));
- memcpy((char *)&b2_2, keyval2 + kptr->sd[i].s_keystart,
- sizeof(b2_2));
- b4_1 = b2_1;
- b4_2 = b2_2;
- }
- else
- {
- memcpy((char *)&b4_1, (char *)(keyval1 + kptr->sd[i].s_keystart),
- sizeof(b4_1));
- memcpy((char *)&b4_2, (char *)(keyval2 + kptr->sd[i].s_keystart),
- sizeof(b4_2));
- }
- if (b4_1 < b4_2)
- iostat = -1;
- else if (b4_1 > b4_2)
- iostat = 1;
- break;
-
- case FLTTYP: /* single precision FP number (usually 4 long) */
- memcpy((char *)&ftmp1, keyval1 + kptr->sd[i].s_keystart,
- sizeof(FLOAT32));
- memcpy((char *)&ftmp2, keyval2 + kptr->sd[i].s_keystart,
- sizeof(FLOAT32));
- dtmp1 = (FLOAT64) ftmp1;
- dtmp2 = (FLOAT64) ftmp2;
- /*FALLTHROUGH*/
-
- case DBLTYP: /* double precision FP number (usually 8 long) */
- if (kptr->sd[i].s_vtyp == DBLTYP)
- {
- memcpy((char *)&dtmp1, keyval1 + kptr->sd[i].s_keystart,
- sizeof(FLOAT64));
- memcpy((char *)&dtmp2, keyval2 + kptr->sd[i].s_keystart,
- sizeof(FLOAT64));
- }
- if (dtmp1 < dtmp2)
- iostat = -1;
- else if (dtmp1 > dtmp2)
- iostat = 1;
- break;
- }
- }
-
- /* check the dup suffix for a DUPLICATE key */
- if (!iostat && mode == KEY_DUPLICATE)
- {
- /* compare the segments according to type */
- memcpy((char *)&dupnum1, keyval1 + kptr->sd[DUPSEG].s_keystart,
- kptr->sd[DUPSEG].s_leng);
- memcpy((char *)&dupnum2, keyval2 + kptr->sd[DUPSEG].s_keystart,
- kptr->sd[DUPSEG].s_leng);
- if (dupnum1 < dupnum2)
- iostat = -1;
- else if (dupnum1 > dupnum2)
- iostat = 1;
- }
-
- return(iostat);
- }
-
-
- int
- PT_flush_node(fd_sys, lev)
- int fd_sys;
- int lev;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int iostat = IOGOOD;
-
- if (kptr->c_elt[lev] >= 0 && kptr->changes[lev])
- {
- kptr->changes[lev] = FLUSH_LEVEL;
- iostat = PT_writeidx(fd_sys, lev);
- }
-
- return(iostat);
- }
-
-
- int
- PT_flush_cache(fd_sys)
- int fd_sys;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- int ck, lev, iostat;
-
- ck = fptr->cur_key;
-
- for (fptr->cur_key = 0; fptr->cur_key < fptr->key_cnt; fptr->cur_key++)
- for (lev = 0; lev < aptr->keyinfo[fptr->cur_key].k_levs; lev++)
- if ((iostat = PT_flush_node(fd_sys, lev)) != IOGOOD)
- break;
-
- fptr->cur_key = ck;
-
- return(iostat);
- }
-
-
- /**********************************************************************
- * copies index node element structure members from oldelt to newelt *
- **********************************************************************/
- void
- PT_cpyelt(newelt, oldelt, keylen)
- BELT *newelt;
- BELT *oldelt;
- int keylen;
- {
- newelt->offset = oldelt->offset;
- memcpy(newelt->keyval, oldelt->keyval, keylen);
- }
-
-
- void
- PT_cpynode(fd_sys, node1, node2)
- int fd_sys;
- BNODE *node1;
- BNODE *node2;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int i;
-
- node1->level = node2->level;
- node1->num_used = node2->num_used;
- for (i = 0; i < aptr->maxelts; i++)
- PT_cpyelt(&(node1->elt[i]), &(node2->elt[i]), kptr->k_leng);
- }
-
-
- /*********************************
- * fills an element with zeroes *
- *********************************/
- void
- PT_zeronode(fd_sys, nodeptr)
- int fd_sys;
- BNODE *nodeptr;
- {
- AFDDEF *aptr = &PT_fd[fd_sys];
- int i;
-
- nodeptr->num_used = 0;
- for (i = 0; i < aptr->maxelts; i++)
- PT_zeroelt(fd_sys, &(nodeptr->elt[i]));
- }
-
-
- /*********************************
- * fills an element with zeroes *
- *********************************/
- void
- PT_zeroelt(fd_sys, eltp)
- int fd_sys;
- BELT *eltp;
- {
- eltp->offset = 0L;
- memset(eltp->keyval, 0, PT_fd[fd_sys].keyinfo[fd[fd_sys].cur_key].k_leng);
- }
-
-
- /***********************************************************************
- * return data record offset of first logical record by current index *
- ***********************************************************************/
- long
- PT_first_key(fd_sys)
- int fd_sys;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int lev;
- long offset;
-
- /* descend to leaf level on left side of btree */
- lev = -1;
- do
- {
- if (PT_readidx(fd_sys, ++lev, 0) != IOGOOD)
- offset = PTNOPTR;
- else if (kptr->nodebuff[lev].num_used <= 0)
- offset = PTNOPTR;
- else
- {
- kptr->c_elt[lev] = 0;
- offset = kptr->nodebuff[lev].elt[0].offset;
- }
- }
- while (offset != PTNOPTR && kptr->nodebuff[lev].level > 0);
-
- return(offset);
- }
-
-
- /**********************************************************************
- * return data record offset of last logical record by current index *
- **********************************************************************/
- long
- PT_last_key(fd_sys)
- int fd_sys;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int lev, elt;
- long offset;
-
- /* descend to leaf level on right side of btree */
- elt = 0;
- lev = -1;
- do
- {
- if (PT_readidx(fd_sys, ++lev, elt - 1) != IOGOOD)
- offset = PTNOPTR;
- else if ((elt = kptr->nodebuff[lev].num_used) <= 0)
- offset = PTNOPTR;
- else
- {
- kptr->c_elt[lev] = elt - 1;
- offset = kptr->nodebuff[lev].elt[elt - 1].offset;
- }
- }
- while (offset != PTNOPTR && kptr->nodebuff[lev].level > 0);
-
- return(offset);
- }
-
-
- /**********************************************************************
- * return data record offset of next logical record by current index *
- **********************************************************************/
- long
- PT_next_key(fd_sys)
- int fd_sys;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int lev, elt, iostat;
- long offset;
-
- /* climb the tree until there is a "backup" point */
- lev = kptr->nodebuff[0].level;
- elt = kptr->c_elt[lev];
- while (lev > 0 && elt + 1 >= kptr->nodebuff[lev].num_used)
- elt = kptr->c_elt[--lev];
-
- if (elt < 0 || elt + 1 >= kptr->nodebuff[lev].num_used)
- offset = PTNOPTR;
- else
- {
- /* backup and descend on the left-hand side */
- elt++;
- iostat = IOGOOD;
- while (kptr->nodebuff[lev].level > 0)
- {
- if ((iostat = PT_readidx(fd_sys, ++lev, elt)) != IOGOOD)
- break;
- elt = 0;
- }
- if (iostat != IOGOOD || elt >= kptr->nodebuff[lev].num_used)
- offset = PTNOPTR;
- else
- {
- offset = kptr->nodebuff[lev].elt[elt].offset;
- kptr->c_elt[lev] = elt;
- }
- }
-
- return(offset);
- }
-
-
- /**************************************************************************
- * return data record offset of previous logical record by current index *
- **************************************************************************/
- long
- PT_prev_key(fd_sys)
- int fd_sys;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int lev, elt, iostat;
- long offset;
-
- /* climb the tree until there is a "backup" point */
- lev = kptr->nodebuff[0].level;
- elt = kptr->c_elt[lev];
- while (lev > 0 && !elt)
- elt = kptr->c_elt[--lev];
-
- if (elt <= 0 || elt > kptr->nodebuff[lev].num_used)
- offset = PTNOPTR;
- else
- {
- /* backup and descend on the right-hand side */
- elt--;
- iostat = IOGOOD;
- while (kptr->nodebuff[lev].level > 0)
- {
- if ((iostat = PT_readidx(fd_sys, ++lev, elt)) != IOGOOD)
- break;
- elt = kptr->nodebuff[lev].num_used - 1;
- }
- if (iostat != IOGOOD || elt < 0)
- offset = PTNOPTR;
- else
- {
- offset = kptr->nodebuff[lev].elt[elt].offset;
- kptr->c_elt[lev] = elt;
- }
- }
-
- return(offset);
- }
-
-
- /***************************************************************
- * return data record offset of first logical record matching *
- * (or greater than) the given key, by current index *
- ***************************************************************/
- long
- PT_gteq_key(fd_sys, keyval, exact)
- int fd_sys;
- char *keyval;
- int exact;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int lev, elt = 0, cmp;
- long offset;
-
- lev = -1;
- for (;;)
- {
- if ((cmp = PT_readidx(fd_sys, ++lev, elt)) != IOGOOD)
- {
- abort_mess("DIAG: readidx( lev=%d , elt=%d): %s\n", lev, elt,
- io_tran(cmp));
- cmp = 1;
- break;
- }
-
- /* tree is empty */
- if (kptr->nodebuff[lev].num_used == 0)
- {
- cmp = 1;
- break;
- }
-
- /* set elt to key in node greater or equal to keyval */
- cmp = PT_find_match(fd_sys, keyval, &(kptr->nodebuff[lev]), &elt);
- kptr->c_elt[lev] = elt;
-
- if (kptr->nodebuff[lev].level <= 0)
- break;
- else if (cmp > 0)
- kptr->c_elt[lev] = --elt;
- }
-
- if (!cmp || (cmp < 0 && !exact))
- offset = kptr->nodebuff[lev].elt[elt].offset;
- else
- offset = PTNOPTR;
-
- return(offset);
- }
-
-
- /***********************************************************
- * Extract the segments of a key from the data record and *
- * combine them to form the key string. *
- ***********************************************************/
- void
- PT_get_key(fd_sys, buffer, keyval)
- int fd_sys;
- char *buffer;
- char *keyval;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int i, s_leng, s_kstart;
-
- for (i = 0; i < kptr->k_segs; i++)
- {
- s_leng = kptr->sd[i].s_leng;
- s_kstart = kptr->sd[i].s_keystart;
- memcpy(keyval + s_kstart, buffer + kptr->sd[i].s_recstart, s_leng);
- }
-
- if (kptr->k_type == KEY_DUPLICATE)
- {
- s_leng = kptr->sd[DUPSEG].s_leng;
- s_kstart = kptr->sd[DUPSEG].s_keystart;
- memset(&keyval[s_kstart], 0, s_leng);
- }
- }
-
-
- char *
- PT_fmtkey(kptr, keyval)
- KINFO *kptr;
- char *keyval;
- {
- static char buf[81], *ptr;
- int i, s_leng, s_kstart, s_vtyp;
- WORD16 b2;
- WORD32 b4;
- FLOAT32 ftmp;
- FLOAT64 dtmp;
-
- *(ptr = buf) = 0;
- sprintf(buf, "0x%lx:", keyval);
- ptr = buf + strlen(buf);
- for (i = 0; i < kptr->k_segs; i++)
- {
- if (i)
- strcat(ptr, ":"), ptr += 2;
-
- s_leng = kptr->sd[i].s_leng;
- s_kstart = kptr->sd[i].s_keystart;
- s_vtyp = kptr->sd[i].s_vtyp;
-
- /* compare the segments according to type */
- switch (s_vtyp)
- {
- case CHRTYP :
- case LOGTYP :
- case MEMTYP :
- case DATTYP :
- sprintf(ptr, "[%*.*s]", s_leng, s_leng, &keyval[s_kstart]);
- break;
- case INTTYP: /* two byte integer */
- case LNGTYP: /* four byte integer */
- if (s_leng == sizeof(WORD16))
- {
- memcpy((char *)&b2, &keyval[s_kstart], sizeof(WORD16));
- b4 = (WORD32)b2;
- }
- else
- memcpy((char *)&b4, &keyval[s_kstart], sizeof(WORD32));
- sprintf(ptr, "[%5ld]", b4);
- break;
- case FLTTYP: /* single precision FP number (usually 4 long) */
- case DBLTYP: /* double precision FP number (usually 8 long) */
- if (s_vtyp == FLTTYP)
- {
- memcpy((char *)&ftmp, &keyval[s_kstart], sizeof(FLOAT32));
- dtmp = (FLOAT64)ftmp;
- }
- else
- memcpy((char *)&dtmp, &keyval[s_kstart], sizeof(FLOAT64));
- sprintf(ptr, "[%lf]", dtmp);
- break;
- default:
- strcat(ptr, "???");
- break;
- }
-
- ptr = buf + strlen(buf);
- }
-
- if (kptr->k_type == KEY_DUPLICATE)
- {
- s_leng = kptr->sd[DUPSEG].s_leng;
- s_kstart = kptr->sd[DUPSEG].s_keystart;
-
- if (s_leng == sizeof(WORD16))
- {
- memcpy((char *)&b2, &keyval[s_kstart], sizeof(WORD16));
- b4 = (WORD32)b2;
- }
- else
- memcpy((char *)&b4, &keyval[s_kstart], sizeof(WORD32));
- sprintf(ptr, ":<%ld>", b4);
- }
-
- return(buf);
- }
-
-
- void
- PT_makenodes(fd_sys, kptr, num)
- int fd_sys;
- KINFO *kptr;
- int num;
- {
- AFDDEF *aptr = &PT_fd[fd_sys];
- int i, j, pt_size;
- char *ptr;
-
- kptr->k_levs = num;
- kptr->keyval = NULL;
- kptr->c_elt = (WORD16 *)alloc(sizeof(WORD16) * num);
- kptr->changes = (WORD16 *)alloc(sizeof(WORD16) * num);
- kptr->nodeoffset = (WORD32 *)alloc(sizeof(WORD32) * num);
- kptr->nodebuff = (BNODE *)alloc(sizeof(BNODE) * num);
-
- for (i = 0; i < num ; i++)
- {
- kptr->c_elt[i] = -1;
- kptr->changes[i] = 0;
- kptr->nodeoffset[i] = PTNOPTR;
- kptr->nodebuff[i].elt = (BELT *)alloc(sizeof(BELT) * aptr->maxelts);
- pt_size = (kptr->k_leng + 3) / 4;
- pt_size *= 4;
- ptr = alloc(pt_size * aptr->maxelts);/*LEFTOVER*/
- for (j = 0; j < aptr->maxelts; j++)
- kptr->nodebuff[i].elt[j].keyval = ptr + j * pt_size;
- kptr->nodebuff[i].level = num - i - 1;
- if (kptr->nodebuff[i].level < 0)
- abort_mess("\rDIAG: makenodes( level[%d]=%d )\r\n", i,
- kptr->nodebuff[i].level);
- PT_zeronode(fd_sys, &(kptr->nodebuff[i]));
- }
- }
-
-
- int
- PT_resize(fd_sys, kptr, to)
- int fd_sys;
- KINFO *kptr;
- int to;
- {
- KINFO *ktmp;
- int iostat = IOGOOD, i, from, first = FALSE;
-
- if ((from = kptr->k_levs) < 0)
- {
- kptr->k_levs = from = 1;
- first = TRUE;
- }
- else if (from - to != 1 && from - to != -1)
- abort_mess("\rDIAG: resize( from=%d , to=%d )\r\n", from, to);
-
- /* save the old arrays and their contents */
- ktmp = (KINFO *)alloc(sizeof(KINFO));
- ktmp->k_leng = kptr->k_leng;
- ktmp->k_type = kptr->k_type;
- ktmp->k_segs = kptr->k_segs;
- ktmp->didxptr = kptr->didxptr;
- for (i = 0; i <= MAXSEGS; i++)
- ktmp->sd[i] = kptr->sd[i];
- PT_makenodes(fd_sys, ktmp, from);
- for (i = 0; i < from; i++)
- {
- ktmp->c_elt[i] = kptr->c_elt[i];
- ktmp->changes[i] = kptr->changes[i];
- ktmp->nodeoffset[i] = kptr->nodeoffset[i];
- PT_cpynode(fd_sys, &(ktmp->nodebuff[i]), &(kptr->nodebuff[i]));
- }
- /* save the current key pointer in a safe place */
- ktmp->keyval = kptr->keyval;
- kptr->keyval = NULL;
-
- /* grab a new set of the appropriate dimensions */
- PT_freenodes(fd_sys, kptr);
- PT_makenodes(fd_sys, kptr, to);
-
- /* just planted */
- if (first)
- {
- kptr->c_elt[0] = ktmp->c_elt[0];
- kptr->changes[0] = ktmp->changes[0];
- kptr->nodeoffset[0] = ktmp->nodeoffset[0];
- PT_cpynode(fd_sys, &(kptr->nodebuff[0]), &(ktmp->nodebuff[0]));
- }
-
- /* growing */
- else if (from < to)
- {
- for (i = 1; i < to; i++)
- {
- kptr->c_elt[i] = ktmp->c_elt[i - 1];
- kptr->changes[i] = ktmp->changes[i - 1];
- kptr->nodeoffset[i] = ktmp->nodeoffset[i - 1];
- PT_cpynode(fd_sys, &(kptr->nodebuff[i]), &(ktmp->nodebuff[i - 1]));
- }
-
- /* save the new second level */
- kptr->nodeoffset[1] = PTNOPTR;
- iostat = PT_writeidx(fd_sys, 1);
-
- /* save the new top level */
- kptr->c_elt[0] = 0;
- kptr->nodeoffset[0] = ktmp->nodeoffset[0];
- kptr->nodebuff[0].level = to - 1;
- if (kptr->nodebuff[0].level < 0)
- abort_mess("\rDIAG: resize( level[0]=%d )\r\n",
- kptr->nodebuff[0].level);
- kptr->nodebuff[0].num_used = 0;
- iostat = PT_add_elt(fd_sys, 0, kptr->nodeoffset[1],
- kptr->nodebuff[1].elt[kptr->nodebuff[1].num_used - 1].keyval);
- }
-
- /* shrinking */
- else
- {
- for (i = 0; i < to; i++)
- {
- kptr->c_elt[i] = ktmp->c_elt[i + 1];
- kptr->changes[i] = ktmp->changes[i + 1];
- kptr->nodeoffset[i] = ktmp->nodeoffset[i + 1];
- PT_cpynode(fd_sys, &(kptr->nodebuff[i]), &(ktmp->nodebuff[i + 1]));
- }
-
- /* save the new top level */
- kptr->nodeoffset[0] = ktmp->nodeoffset[0];
- iostat = PT_writeidx(fd_sys, 0);
-
- /* re-cycle the old top level */
- iostat = PT_keyrecycle(fd_sys, ktmp->nodeoffset[1]);
- }
-
- /* restore the current key pointer */
- kptr->keyval = ktmp->keyval;
- ktmp->keyval = NULL;
-
- PT_freenodes(fd_sys, ktmp);
- free(ktmp);
-
- return(iostat);
- }
-
-
- void
- PT_freenodes(fd_sys, kptr)
- int fd_sys;
- KINFO *kptr;
- {
- int i;
-
- if (kptr)
- {
- if (kptr->nodebuff)
- {
- for (i = 0; i < kptr->k_levs; i++)
- if (kptr->nodebuff[i].elt)
- {
- if (kptr->nodebuff[i].elt[0].keyval)
- free(kptr->nodebuff[i].elt[0].keyval);
- free((char *)kptr->nodebuff[i].elt);
- }
- free((char *)kptr->nodebuff);
- kptr->nodebuff = (BNODE *)0;
- }
- if (kptr->nodeoffset)
- {
- free((char *)kptr->nodeoffset);
- kptr->nodeoffset = (WORD32 *)0;
- }
- if (kptr->changes)
- {
- free((char *)kptr->changes);
- kptr->changes = (WORD16 *)0;
- }
- if (kptr->c_elt)
- {
- free((char *)kptr->c_elt);
- kptr->c_elt = (WORD16 *)0;
- }
- if (kptr->keyval)
- {
- free(kptr->keyval);
- kptr->keyval = NULL;
- }
-
- kptr->k_levs = 0;
- }
- }
-
-
- int
- PT_recrecycle(fd_sys, offset)
- int fd_sys;
- long offset;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- int iostat;
- WORD32 b4;
-
- /* stack the record for re-cycling */
- if (lseek(aptr->fd_idx, aptr->ddatptr, FDIR_BEGIN) != aptr->ddatptr)
- iostat = IOIDXSEEK;
- else
- iostat = PT_readnum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- if (iostat == IOGOOD)
- {
- if (lseek(fptr->fd_num, offset, FDIR_BEGIN) != offset)
- iostat = IOIDXSEEK;
- else
- iostat = PT_writenum(fptr->fd_num, (char *)&b4, sizeof(b4));
- }
- if (iostat == IOGOOD)
- {
- b4 = offset;
- if (lseek(aptr->fd_idx, aptr->ddatptr, FDIR_BEGIN) != aptr->ddatptr)
- iostat = IOIDXSEEK;
- else
- iostat = PT_writenum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- }
-
- return(iostat);
- }
-
-
- long
- PT_recreuse(fd_sys)
- int fd_sys;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- long offset = PTNOPTR;
- WORD32 b4;
- int iostat;
-
- /* pop the free record stack */
- if (lseek(aptr->fd_idx, aptr->ddatptr, FDIR_BEGIN) != aptr->ddatptr)
- iostat = IOIDXSEEK;
- else
- {
- iostat = PT_readnum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- if (iostat == IOGOOD)
- {
- aptr->doffset = offset = b4;
- if (offset != PTNOPTR)
- iostat = i_lockrec(fd_sys, NULL);
- }
- }
- if (iostat == IOGOOD && offset != PTNOPTR)
- {
- if (lseek(fptr->fd_num, offset, FDIR_BEGIN) != offset)
- iostat = IODATSEEK;
- else
- iostat = PT_readnum(fptr->fd_num, (char *)&b4, sizeof(b4));
- }
- if (iostat == IOGOOD && offset != PTNOPTR)
- {
- if (lseek(aptr->fd_idx, aptr->ddatptr, FDIR_BEGIN) != aptr->ddatptr)
- iostat = IOIDXSEEK;
- else
- iostat = PT_writenum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- }
-
- if (iostat != IOGOOD)
- aptr->doffset = offset = PTNOPTR;
-
- return(offset);
- }
-
-
- int
- PT_keyrecycle(fd_sys, offset)
- int fd_sys;
- long offset;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int iostat;
- WORD32 b4;
-
- /* stack the node for re-cycling */
- if (lseek(aptr->fd_idx, kptr->didxptr, FDIR_BEGIN) != kptr->didxptr)
- iostat = IOIDXSEEK;
- else
- iostat = PT_readnum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- if (iostat == IOGOOD)
- {
- if (lseek(aptr->fd_idx, offset, FDIR_BEGIN) != offset)
- iostat = IOIDXSEEK;
- else
- iostat = PT_writenum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- }
- if (iostat == IOGOOD)
- {
- b4 = offset;
- if (lseek(aptr->fd_idx, kptr->didxptr, FDIR_BEGIN) != kptr->didxptr)
- iostat = IOIDXSEEK;
- else
- iostat = PT_writenum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- }
-
- return(iostat);
- }
-
-
- long
- PT_keyreuse(fd_sys)
- int fd_sys;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- long offset = PTNOPTR;
- WORD32 b4;
- int iostat;
-
- /* pop the free node stack */
- if (lseek(aptr->fd_idx, kptr->didxptr, FDIR_BEGIN) != kptr->didxptr)
- iostat = IOIDXSEEK;
- else
- if ((iostat = PT_readnum(aptr->fd_idx, (char *)&b4, sizeof(b4))) == IOGOOD)
- offset = b4;
- if (iostat == IOGOOD && offset != PTNOPTR)
- {
- if (lseek(aptr->fd_idx, offset, FDIR_BEGIN) != offset)
- iostat = IOIDXSEEK;
- else
- iostat = PT_readnum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- }
- if (iostat == IOGOOD && offset != PTNOPTR)
- {
- if (lseek(aptr->fd_idx, kptr->didxptr, FDIR_BEGIN) != kptr->didxptr)
- iostat = IOIDXSEEK;
- else
- iostat = PT_writenum(aptr->fd_idx, (char *)&b4, sizeof(b4));
- }
-
- if (iostat != IOGOOD)
- offset = PTNOPTR;
-
- return(offset);
- }
-
-
- /************************************************************************
- * Position data file pointers and read a record into the local buffer *
- ************************************************************************/
- int
- PT_get_rec(fd_sys, buffer)
- int fd_sys;
- char *buffer;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int lev, elt, iostat;
-
- if (aptr->doffset == PTNOPTR)
- iostat = IONOKEY;
- else if ((iostat = i_lockrec(fd_sys, buffer)) != IOGOOD)
- aptr->doffset = PTNOPTR;
- else
- {
- lev = kptr->nodebuff[0].level;
- elt = kptr->c_elt[lev];
- if (!kptr->keyval)
- kptr->keyval = alloc(kptr->k_leng);
- memcpy(kptr->keyval, kptr->nodebuff[lev].elt[elt].keyval,
- kptr->k_leng);
-
- if (kptr->nodebuff[lev].elt[elt].offset != aptr->doffset)
- {
- errmsg("DIAG: record data and index out of sync");
- abort_mess("\rDIAG: get_rec( %s[%d][%d][%d]=%ld ) [%ld]\r\n",
- aptr->iname, fptr->cur_key + 1, lev, elt,
- kptr->nodebuff[lev].elt[elt].offset, aptr->doffset);
- }
- if (iostat == IOGOOD)
- iostat = PT_readdata(fd_sys, buffer);
- }
-
- return(iostat);
- }
-
-
- #ifndef INCREMENTAL_DUP_VALUES
- int
- PT_find_key(fd_sys, buf)
- int fd_sys;
- char *buf;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- int iostat = IOGOOD;
-
- if (!kptr->keyval)
- kptr->keyval = alloc(kptr->k_leng);
- PT_get_key(fd_sys, buf, kptr->keyval);
-
- if (kptr->k_type == KEY_DUPLICATE)
- iostat = PT_new_dup(fd_sys, kptr->keyval);
-
- if (PT_gteq_key(fd_sys, kptr->keyval, TRUE) == PTNOPTR)
- iostat = IONOKEY;
-
- return(iostat);
- }
- #endif
-
-
- #ifdef INCREMENTAL_DUP_VALUES
- int
- PT_find_key(fd_sys, buf)
- int fd_sys;
- char *buf;
- {
- FDDEF *fptr = &fd[fd_sys];
- AFDDEF *aptr = &PT_fd[fd_sys];
- KINFO *kptr = &(aptr->keyinfo[fptr->cur_key]);
- long offset;
- int lev, elt, iostat = IOERROR;
-
- if (!kptr->keyval)
- kptr->keyval = alloc(kptr->k_leng);
- PT_get_key(fd_sys, buf, kptr->keyval);
-
- offset = PT_gteq_key(fd_sys, kptr->keyval, FALSE);
-
- while (offset != PTNOPTR && offset != aptr->doffset)
- {
- lev = kptr->nodebuff[0].level;
- elt = kptr->c_elt[lev];
- if (PT_keycmp(fd_sys, kptr->keyval,
- kptr->nodebuff[lev].elt[elt].keyval, KEY_UNIQUE))
- offset = PTNOPTR;
- else
- offset = PT_next_key(fd_sys);
- }
-
- if (offset != PTNOPTR)
- {
- lev = kptr->nodebuff[0].level;
- elt = kptr->c_elt[lev];
- memcpy(kptr->keyval, kptr->nodebuff[lev].elt[elt].keyval, kptr->k_leng);
- iostat = IOGOOD;
- }
-
- return(iostat);
- }
- #endif
-