libDtSearch: Remove define ONE_DB which is always off for CDE
[oweals/cde.git] / cde / lib / DtSearch / raima / connect.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: connect.c /main/2 1996/05/09 03:56:41 drk $ */
24 /*
25  *   COMPONENT_NAME: austext
26  *
27  *   FUNCTIONS: Pi
28  *              d_connect
29  *              sortcmp
30  *
31  *   ORIGINS: 157
32  *
33  *   OBJECT CODE ONLY SOURCE MATERIALS
34  */
35 /*-----------------------------------------------------------------------
36    connect.c -- db_VISTA set connection module
37
38    (C) Copyright 1985, 1986, 1987 by Raima Corp.
39 -----------------------------------------------------------------------*/
40
41 /* ********************** EDIT HISTORY *******************************
42
43  SCR    DATE    INI                   DESCRIPTION
44 ----- --------- --- -----------------------------------------------------
45       04-Aug-88 RTK MULTI_TASK changes
46 */
47
48 #include <stdio.h>
49 #include "vista.h"
50 #include "dbtype.h"
51
52 /* Internal function Prototypes */
53 static int sortcmp(P1(SET_ENTRY *) Pi(char *) 
54                                   Pi(char *));
55
56 /* set pointer structure definition */
57 typedef struct {
58    LONG    total;     /* total number of members in set */
59    DB_ADDR first;     /* database address of first member in set */
60    DB_ADDR last;      /* database address of last member in set */
61 #ifndef  NO_TIMESTAMP
62    ULONG   timestamp; /* set update timestamp - if used */
63 #endif
64 } SET_PTR;
65
66 /* member pointer structure definition */
67 typedef struct {
68    DB_ADDR owner;     /* database address of owner record */
69    DB_ADDR prev;      /* database address of previous member in set */
70    DB_ADDR next;      /* database address of next member in set */
71 } MEM_PTR;
72
73
74 /* Connect the current record as member of set
75 */
76 int
77 d_connect(set TASK_PARM DBN_PARM)
78 int set; /* Set constant */
79 TASK_DECL
80 DBN_DECL /* Database number */
81 {
82    MEM_PTR crmp;          /* current record's member pointer */
83    SET_PTR cosp;          /* current owner's set pointer */
84    MEM_PTR cmmp;          /* current member's member pointer */
85    MEM_PTR nmmp;          /* next member's member pointer */
86    char *crec;            /* ptr to current record contents in cache */
87    char *orec;            /* ptr to current owner record contents in cache */
88    char *mrec;            /* ptr to current member record contents in cache */
89    char *nrec;            /* ptr to next member record contents in cache */
90    DB_ADDR mdba;          /* db address of current member record */
91    DB_ADDR ndba;          /* db address of next member record */
92    INT ordering;          /* set order control variable */
93    int stat, compare;     /* status code & sort comparison result */
94 #ifndef  NO_TIMESTAMP
95    FILE_NO file;
96 #endif
97    SET_ENTRY *set_ptr;
98    DB_ADDR *co_ptr;
99    DB_ADDR *cm_ptr;
100
101    DB_ENTER(DB_ID TASK_ID LOCK_SET(SET_IO));
102
103    if (nset_check(set, &set, (SET_ENTRY **)&set_ptr) != S_OKAY)
104       RETURN( db_status );
105
106    /* make sure we have a current record */
107    if ( curr_rec == NULL_DBA )
108       RETURN( dberr(S_NOCR) );
109
110    /* make sure we have a current owner */
111    if ( *(co_ptr = &curr_own[set]) == NULL_DBA )
112       RETURN( dberr(S_NOCO) );
113
114    crec = orec = mrec = nrec = NULL;
115
116    /* read current record */
117    if ( dio_read( curr_rec, (char **)&crec, PGHOLD ) != S_OKAY )
118       RETURN( db_status );
119    
120    /* read owner record */
121    if ( (stat = dio_read(*co_ptr, (char **)&orec, PGHOLD)) != S_OKAY ) {
122       dio_release( curr_rec );
123       RETURN( stat );
124    }
125    /* get copy of current record's member ptr for set */
126    if ( (stat = r_gmem(set, crec, (char *)&crmp)) != S_OKAY )
127       goto quit;
128
129    /* ensure record not already connected to set */
130    if ( ! crmp.owner == NULL_DBA ) { 
131       stat = dberr(S_ISOWNED);
132       goto quit;
133    }
134    /* get set pointer from owner */
135    if ( r_gset(set, orec, (char *)&cosp) != S_OKAY ) {
136       stat = db_status == S_INVOWN ? dberr(S_SYSERR) : db_status;
137       goto quit;
138    }
139    /* set current record's owner to current owner of set */
140    crmp.owner = *co_ptr;
141
142    cm_ptr = &curr_mem[set];
143    /* make insertion based on set order specfication */
144    if (cosp.first == NULL_DBA) {
145       /* set is empty */
146       /* set current owner's first and last to current record */
147       cosp.first = cosp.last = curr_rec;
148
149       /* set current record's next and previous to null */
150       crmp.next = crmp.prev = NULL_DBA;
151       goto inserted;
152    }
153    /* order is as specified in DDL */
154    ordering = set_ptr->st_order;
155
156    while (TRUE) switch (ordering) {
157       case ASCENDING:
158       case DESCENDING:
159          /* perform a linked insertion sort on set -
160             position the current member to the proper place and then
161             switch to order NEXT */
162          for (mdba = cosp.first; TRUE; mdba = cmmp.next) {
163             /* read member record and get member pointer from member
164                record */
165             if (((stat = dio_read(mdba, (char * *)&mrec, NOPGHOLD)) != S_OKAY) ||
166                 ((stat = r_gmem(set, mrec, (char *)&cmmp)) != S_OKAY))
167                goto quit;
168
169             /* compare sort fields of current record with member record */
170             compare = sortcmp(set_ptr, crec, mrec);
171             if ((ordering == ASCENDING) ? (compare < 0) : (compare > 0)) {
172                /* found insertion position -
173                   make previous member the current member of set and
174                   switch to next order processing */
175                *cm_ptr = cmmp.prev;
176                ordering = NEXT;
177                break;
178             }
179             if ( cmmp.next == NULL_DBA ) {
180                /* connect at end of list */
181                *cm_ptr = mdba;
182                ordering = NEXT;
183                break;
184             }
185          }
186          break;
187       case FIRST:
188          crmp.next = cosp.first;
189          /* read current owner's first member and get first member's
190             member pointer
191          */
192          mdba = cosp.first;
193          if (((stat = dio_read(mdba, (char * *)&mrec, PGHOLD)) != S_OKAY) ||
194              ((stat = r_gmem(set, mrec, (char *)&cmmp)) != S_OKAY))
195             goto quit;
196
197          /* set current member's previous, and current owner's first, to
198             current record */
199          cmmp.prev = cosp.first = curr_rec;
200          goto inserted;
201       case NEXT:
202          if (!*cm_ptr) {
203             /* if no current member, next is same as first */
204             ordering = FIRST;
205             break;
206          }
207          /* insert record after current member */
208          mdba = *cm_ptr;
209
210          /* read current member record and get member pointer from
211             current member
212          */
213          if (((stat = dio_read(mdba, (char * *)&mrec, PGHOLD)) != S_OKAY) ||
214              ((stat = r_gmem(set, mrec, (char *)&cmmp)) != S_OKAY))
215             goto quit;
216
217          /* set current record's next to current member's next */
218          crmp.next = cmmp.next;  
219
220          /* set current record's prev to current member */
221          crmp.prev = mdba;       
222
223          /* set current member's next ro current record */
224          cmmp.next = curr_rec;   
225
226          if (crmp.next == NULL_DBA) {
227             /* current record at end of list -
228                update set pointer's last member */
229             cosp.last = curr_rec;
230             goto inserted;
231          }
232          /* read next member record and member pointer from next member */
233          ndba = crmp.next;
234          if (((stat = dio_read(ndba, (char * *)&nrec, PGHOLD)) != S_OKAY) ||
235              ((stat = r_gmem(set, nrec, (char *)&nmmp)) != S_OKAY))
236             goto quit;
237
238          /* set previous pointer in next member to current record */
239          nmmp.prev = curr_rec;
240          goto inserted;
241       case LAST:
242          /* set current member to owner's last pointer */
243          *cm_ptr = cosp.last;
244          /* switch to order next */
245          ordering = NEXT;
246          break;
247       default:
248          /* there are no other possible orderings! */
249          RETURN( dberr(S_SYSERR) );
250    }                                    /* while switch */
251 inserted:
252    /* increment total members in set */
253    ++cosp.total;
254 #ifndef  NO_TIMESTAMP
255    /* check for timestamp */
256    if ( set_ptr->st_flags & TIMESTAMPED ) {
257       file = NUM2INT((FILE_NO)((*co_ptr >> FILESHIFT) & FILEMASK), ft_offset);
258       cosp.timestamp = dio_pzgetts(file);
259    }
260 #endif
261    if ( mrec ) { 
262       /* put member pointer back into member record and mark member
263          record as modified
264       */
265       if (((stat = r_pmem(set, mrec, (char *)&cmmp)) != S_OKAY) ||
266           ((stat = dio_write(mdba, NULL, PGFREE)) != S_OKAY))
267          goto quit;
268    }
269    if ( nrec ) { 
270       /* put member pointer back into next record and mark next record
271          as modified
272       */
273       if (((stat = r_pmem(set, nrec, (char *)&nmmp)) != S_OKAY) ||
274           ((stat = dio_write(ndba, NULL, PGFREE)) != S_OKAY))
275          goto quit;
276    }
277    /* put set pointer back into owner record and mark owner record as
278       modified; put member pointer back into current record mark current
279       record as modified */
280    if (((stat = r_pset(set, orec, (char *)&cosp)) != S_OKAY) ||
281        ((stat = dio_write(*co_ptr, NULL, PGFREE)) != S_OKAY) ||
282        ((stat = r_pmem(set, crec, (char *)&crmp)) != S_OKAY) ||
283        ((stat = dio_write(curr_rec, NULL, PGFREE)) != S_OKAY))
284       goto quit;
285
286    /* set current member to current record */
287    *cm_ptr = curr_rec;
288 #ifndef  NO_TIMESTAMP
289    /* check and fetch timestamps */
290    if ( db_tsrecs )
291       d_utscr(&cm_time[set] TASK_PARM);
292    if ( db_tssets )
293       cs_time[set] = cosp.timestamp;
294 #endif
295    RETURN( db_status );
296
297 /* error return */
298 quit:
299    if ( crec ) dio_release( curr_rec );
300    if ( orec ) dio_release( *co_ptr );
301    if ( mrec ) dio_release( mdba );
302    if ( nrec ) dio_release( ndba );
303    RETURN( db_status = stat );
304 }
305
306
307 /* Compare two sort fields
308 */
309 static int sortcmp(set_ptr, mem1, mem2)
310 SET_ENTRY *set_ptr; /* set table entry */
311 char *mem1; /* member record 1 */
312 char *mem2; /* member record 2 */
313 {
314    INT rn1, rn2;  /* record numbers for mem1 & mem2 */
315    MEMBER_ENTRY *mt1, *mt2;
316    MEMBER_ENTRY *mt;
317    int mem, memtot;
318    int cmp;       /* fldcmp result */
319    int maxflds;
320    SORT_ENTRY *srt1_ptr, *srt2_ptr;
321    FIELD_ENTRY *fld_ptr;
322
323    /* extract record numbers from record header */
324    bytecpy(&rn1, mem1, sizeof(INT));
325    rn1 &= ~RLBMASK; /* mask off rlb */
326    bytecpy(&rn2, mem2, sizeof(INT));
327    rn2 &= ~RLBMASK; /* mask off rlb */
328    rn1 += curr_db_table->rt_offset;
329    rn2 += curr_db_table->rt_offset;
330
331    /* locate member_table entries for these record types */
332    mt2 = mt1 = NULL;
333    for (mem = set_ptr->st_members, memtot = mem + set_ptr->st_memtot,
334                                                       mt = &member_table[mem];
335         mem < memtot;
336         ++mem, ++mt) {
337       if ( mt->mt_record == rn1 ) {
338          mt1 = mt;
339          if (mt2 != NULL)
340             break;
341       }
342       if ( mt->mt_record == rn2 ) {
343          mt2 = mt;
344          if (mt1 != NULL)
345             break;
346       }
347    }
348    /* set maxflds to number of sort fields in set (min(mt1,mt2)) */
349    maxflds = (mt1->mt_totsf <= mt2->mt_totsf) ? mt1->mt_totsf : mt2->mt_totsf;
350    
351    /* do comparison for each field */
352    for (srt1_ptr = &sort_table[mt1->mt_sort_fld],
353                                     srt2_ptr = &sort_table[mt2->mt_sort_fld];
354         maxflds--;
355         ++srt1_ptr, ++srt2_ptr) {
356       /* compare the two fields */
357       /* computation is pointer to next sort field in member record */
358       fld_ptr = &field_table[srt1_ptr->se_fld];
359       if ((cmp = fldcmp(fld_ptr, mem1 + fld_ptr->fd_ptr,
360                        mem2 + field_table[srt2_ptr->se_fld].fd_ptr)))
361          return (cmp);  /* return at first unequal fields */
362    }
363    /* fields match */
364    return (0);
365 }
366 /* vpp -nOS2 -dUNIX -nBSD -nVANILLA_BSD -nVMS -nMEMLOCK -nWINDOWS -nFAR_ALLOC -f/usr/users/master/config/nonwin connect.c */