home *** CD-ROM | disk | FTP | other *** search
- /*
- * IWRITE.C - write record.
- *
- * Copyright (c) 1987, Jim Mischel
- * Modifications:
- *
- * 08/13/87 - jim - original coding
- * 08/21/87 - jim - copy source to data buffer before writing
- */
-
- #include "inxdefs.h"
-
- /*
- * iwrite() - add the data from '*source' to the data file. Returns 0 if
- * successful, status on error. If duplicate keys are not permitted and
- * adding the record would casue a duplicate key, the global variable 'ierrno'
- * will be set to I_INVKEY.
- */
- int iwrite(void *d, void *src)
- {
- df_rec *db_control = (df_rec *)d;
- char *source = (char *)src;
-
- inx_rec irec; /* new index record */
- inx_rec save_inx_rec;
- long save_inx_ptr,
- write_pos;
-
- irec.if_flags = 0;
-
- switch (isearch(db_control,(source+db_control->df_key_offset))) {
- case 0 :
- if (!(db_control->df_flags & DF_DUP)) /* check duplicates */
- return(ierror(I_INVKEY)); /* error: duplicate key */
- /*
- * duplicate record key.
- * if the right node is a thread pointer, add the new record at right
- */
- if (db_control->df_inx_buff.if_flags & RTHRD)
- goto set_right;
- /*
- * otherwise get the inorder successor and add the new record as the
- * left son.
- */
- if (iget_next(db_control,&db_control->df_inx_buff)) {
- return(ierrno);
- }
- case -1 : /* insert key at left node */
- /* left node of new node is parent's left node */
- irec.if_left_node = db_control->df_inx_buff.if_left_node;
-
- /* right node of new node is parent */
- irec.if_right_node = db_control->df_inx_ptr;
-
- /* both right and left pointers of new node are thread pointers */
- irec.if_flags = (db_control->df_inx_buff.if_flags & BTHRD) +
- RTHRD + LTHRD;
-
- /* if parent is the header node, this node is end of thread */
- if (db_control->df_inx_ptr == 0L)
- irec.if_flags |= ETHRD;
-
- /* parent's left node points to new node */
- db_control->df_inx_buff.if_left_node = fsize(db_control->df_inx_file);
-
- /* parents left node is NOT a thread pointer */
- db_control->df_inx_buff.if_flags &= (ETHRD+RTHRD);
- break;
- case 1 : /* insert key at right node */
- set_right:
- /* right node of new node is parent's right node */
- irec.if_right_node = db_control->df_inx_buff.if_right_node;
-
- /* left node of new node is parent */
- irec.if_left_node = db_control->df_inx_ptr;
-
- /* both right and left pointers of new node are thread pointers */
- irec.if_flags = (db_control->df_inx_buff.if_flags & ETHRD) +
- RTHRD + LTHRD;
-
- /* parent's right node points to new node */
- db_control->df_inx_buff.if_right_node = fsize(db_control->df_inx_file);
-
- /* parent's right node is NOT a thread pointer */
- db_control->df_inx_buff.if_flags &= (LTHRD+BTHRD);
- break;
- default : return(ierrno); /* read error */
- } /* switch */
-
- /* data record will go to end of data file */
- irec.if_dat_ptr = fsize(db_control->df_dat_file);
-
- /* new record's parent is current node */
- irec.if_parent = db_control->df_inx_ptr;
-
- /* save current index record */
- memcpy(&save_inx_rec,&db_control->df_inx_buff,sizeof(inx_rec));
- save_inx_ptr = db_control->df_inx_ptr; /* save current index pointer */
- write_pos = fsize(db_control->df_inx_file); /* save new index location */
-
- /*
- * Now we update the index and data files. This is done as non-destructively
- * as possible. The new index node is added to the index file first. Then
- * the new data record is added to the end of the data file. The last
- * operation performed is to update the old index record. This ensures
- * the integrity of the binary tree structure. If an error occurs while
- * writing any of the records, the binary tree remains as it was before
- * adding the new node was attempted.
- */
-
- /* add new index node */
- if (iwrite_inx(db_control,&irec,write_pos))
- return(ierrno);
-
- /* add new data record to end of data file */
- memcpy(db_control->df_dat_buff,source,db_control->df_rec_size);
- if (iwrite_dat(db_control,source,fsize(db_control->df_dat_file)))
- return(ierrno);
-
- /* update the old index record */
- if (iwrite_inx(db_control,&save_inx_rec,save_inx_ptr))
- return(ierrno);
-
- /* make index file point to new record */
- if (iread_inx(db_control,write_pos))
- return(ierrno);
-
- db_control->df_flags &= ~DF_DELETE; /* clear deleted record flag */
- return(ierror(0));
- } /* iwrite */