tt/mini_isam: remove all ancient sccsid blocks
[oweals/cde.git] / cde / lib / tt / mini_isam / isfixrec.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 /*%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                   */
24 /*%%  (c) Copyright 1993, 1994 International Business Machines Corp.     */
25 /*%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                    */
26 /*%%  (c) Copyright 1993, 1994 Novell, Inc.                              */
27 /*%%  $XConsortium: isfixrec.c /main/3 1995/10/23 11:39:42 rswiston $                                                    */
28 /*
29  * Copyright (c) 1988 by Sun Microsystems, Inc.
30  */
31
32 /*
33  * isfixrec.c
34  *
35  * Description:
36  *      Fixed length record access (FLRA) module.
37  */
38
39 #include "isam_impl.h"
40
41 /* Local functions */
42 long _fl_getpos();                           /* Get offset in .rec file */
43 int  _fl_deleted();                          /* 0/1 returns 1 if record is deleted */
44 static void remove_from_chain();             /* used by _flrec_wrrec() */
45
46 /*
47  * _flrec_write(fcb, record, recnum, reclen)
48  *
49  * Write a record.
50  *
51  * Input params:
52  *      FCB     File Control Block
53  *      record  record buffer
54  *      reclen  record length (NOT USED)
55  *
56  * Output params:
57  *      recnum  record number of the new record
58  *
59  * Returns 0 if record was written successfully, or -1 if any error.
60  */
61
62 /*ARGSUSED*/
63 int
64 _flrec_write(Fcb *fcb, char *record, Recno *recnum, int reclen)
65 {
66     Recno               recnum2;
67     long                rec_position;
68     char                delflag = FL_RECEXISTS;
69     char                recnobuf [RECNOSIZE];
70
71     /*
72      * Reuse a deleted record if one exits.
73      * Otherwise, extend .rec file by a record.
74      */
75     if (fcb->freerecno != NULL_RECNO) {
76         recnum2 = fcb->freerecno;
77
78         /*
79          * Remove record from the chain of deleted records.
80          */
81         rec_position = _fl_getpos(fcb, recnum2); /* Offset in .rec file */
82         _cp_fromfile(fcb, fcb->datfd, recnobuf, rec_position + 1, RECNOSIZE);
83         fcb->freerecno = ldrecno(recnobuf);
84     }
85     else {
86         recnum2 = ++(fcb->lastrecno);
87
88         /* 
89          * Extend .rec file size if necessary.
90          */
91         while (_fl_getpos(fcb, recnum2 + 1) > fcb->datsize * ISPAGESIZE) {
92             fcb->datsize = _extend_file(fcb, fcb->datfd, fcb->datsize);
93         }
94         rec_position = _fl_getpos(fcb, recnum2); /* Offset in .rec file */
95     }
96
97
98     /*
99      * Copy record to the .at file. Mark record as undeleted.
100      */
101     _cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1); 
102     _cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen); 
103
104     *recnum = recnum2;
105
106     return (ISOK);
107 }
108
109 /*
110  * _flrec_read(fcb, record, recnum, reclen)
111  *
112  * Read a record.
113  *
114  * Input params:
115  *      FCB     File Control Block
116  *      recnum  record number of the record
117  *      reclen  filled with the record size for compatibilty with
118  *              variable length records
119  *
120  * Output params:
121  *      record  record buffer is filled with data
122  *
123  * Returns 0 if record was read successfully, or error code if any error.
124  */
125
126 int
127 _flrec_read(Fcb *fcb, char *record, Recno recnum, int *reclen)
128 {
129     long                rec_position;
130     char                delflag;
131
132     /*
133      * Check that recnum is within the range of existing record numbers.
134      */
135     if (recnum < 1 || recnum > fcb->lastrecno)
136         return (EENDFILE);
137
138     rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
139
140     /*
141      * Check that the record is not marked as deleted.
142      */
143     _cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1); 
144     if (delflag == FL_RECDELETED) {
145         return (ENOREC);
146     }
147
148     /*
149      * Copy record from the .at file. 
150      */
151     _cp_fromfile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen); 
152
153     *reclen = fcb->minreclen;
154
155     return (ISOK);
156 }
157
158 /*
159  * pos = _fl_getpos(fcb, recnum)
160  *
161  * Calculate the position of record in .rec file.
162  */
163
164 long
165 _fl_getpos(Fcb *fcb, Recno recnum)
166 {
167     return ((long)(ISCNTLSIZE + (fcb->minreclen + 1) * (recnum -1)));
168 }
169
170 /*
171  * _flrec_rewrite(fcb, record, recnum, reclen)
172  *
173  * Rewrite a record.
174  *
175  * Input params:
176  *      FCB     File Control Block
177  *      recnum  record number of the record
178  *      record  new record
179  *      int     reclen (NOT USED)
180  *
181  * Returns 0 if record was rewritten successfully, or error code if any error.
182  */
183
184 /*ARGSUSED*/
185 int
186 _flrec_rewrite(Fcb *fcb, char *record, Recno recnum, int reclen)
187 {
188     long                rec_position;
189     char                delflag;
190
191     /*
192      * Check that recnum is within the range of existing record numbers.
193      */
194     if (recnum < 1 || recnum > fcb->lastrecno)
195         return (EENDFILE);
196
197     rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
198
199     /*
200      * Check that the record is not marked as deleted.
201      */
202     _cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1); 
203     if (delflag == FL_RECDELETED) {
204         return (ENOREC);
205     }
206
207     /*
208      * Copy new record to the .rec file. 
209      */
210     _cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen); 
211
212     return (ISOK);
213 }
214
215 /*
216  * _flrec_delete(fcb, recnum)
217  *
218  * Rewrite a record.
219  *
220  * Input params:
221  *      FCB     File Control Block
222  *      recnum  record number of the record
223  *
224  * Returns 0 if record was rewritten successfully, or error code if any error.
225  */
226
227 int
228 _flrec_delete(Fcb *fcb, Recno recnum)
229 {
230     long                rec_position;
231     char                delflag;
232     char                recnobuf [RECNOSIZE];
233
234     /*
235      * Check that recnum is within the range of existing record numbers.
236      */
237     if (recnum < 1 || recnum > fcb->lastrecno)
238         return (EENDFILE);
239
240     rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
241
242     /*
243      * Check that the record is not marked as deleted.
244      */
245     _cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1); 
246     if (delflag == FL_RECDELETED) {
247         return (ENOREC);
248     }
249
250     /*
251      * Set the delete flag to FL_RECDELETED.
252      */
253     delflag = FL_RECDELETED;
254     _cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1);
255
256     /*
257      * Insert record into chain of deleted records.
258      */
259     strecno(fcb->freerecno, recnobuf);
260     _cp_tofile(fcb, fcb->datfd, recnobuf, rec_position + 1, RECNOSIZE);
261     fcb->freerecno = recnum;
262
263     return (ISOK);
264 }
265
266 /*
267  * _flrec_wrrec(fcb, record, recnum, reclen)
268  *
269  * Write a record by record number.
270  *
271  * Input params:
272  *      FCB     File Control Block
273  *      recnum  record number of the record
274  *      record  record buffer
275  *      int     reclen (NOT USED)
276  *
277  * Returns 0 if record was written successfully, or error code if any error.
278  *
279  * Note that _flrec_wrrec() commits updates and syncs the FCB to avoid
280  *      buffer pool overflow.
281  */
282
283 /*ARGSUSED*/
284 int
285 _flrec_wrrec(Fcb *fcb, char *record, Recno recnum, int reclen)
286 {
287     long                rec_position;
288     char                delflag;
289     Recno               recnum2;
290     char                recnumbuf [RECNOSIZE];
291
292     /*
293      * Check that recnum is not negative.
294      */
295     if (recnum < 1)
296         return (EBADARG);
297
298     rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
299
300     if (recnum > fcb->lastrecno)  {
301
302         /*
303          * If the recnum is bigger than the highest record number in the .rec
304          * file, extend the .rec file.
305          */
306         while (_fl_getpos(fcb, recnum + 1) > fcb->datsize * ISPAGESIZE) {
307             fcb->datsize = _extend_file(fcb, fcb->datfd, fcb->datsize);
308             
309             /* Sync the updates to avoid buffer pool overflow. */
310             _isdisk_commit();
311             _isdisk_sync();
312             (void)_isfcb_cntlpg_w2(fcb);
313         }
314
315         /*
316          * Mark all records in the range <fcb->lastrecno+1, recnum>  as
317          * deleted.
318          */
319         delflag = FL_RECDELETED;
320         for (recnum2 = fcb->lastrecno + 1; recnum2 <= recnum; recnum2++) {      
321             _cp_tofile(fcb, fcb->datfd, &delflag, _fl_getpos(fcb, recnum2), 1); 
322             strecno(fcb->freerecno, recnumbuf);
323             _cp_tofile(fcb, fcb->datfd, recnumbuf,
324                        _fl_getpos(fcb, recnum2) + 1, RECNOSIZE); 
325             fcb->freerecno = recnum2;
326             
327             /* Sync the updates to avoid buffer pool overflow. */
328             _isdisk_commit();
329             _isdisk_sync();
330             fcb->lastrecno = recnum;
331             (void)_isfcb_cntlpg_w2(fcb);
332         }
333         
334         /*
335          * Note that the disk structures are in a consistent state now,
336          * the .rec was extended by a few records marked as 'deleted'.
337          * This is important for subsequent rollbacks.
338          */
339     } 
340
341     /*
342      * If recnum specifies a record that has existed, check whether it
343      * has been deleted. _flrec_wrrec() does not override existing record.
344      */
345     _cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1); 
346     if (delflag == FL_RECEXISTS) {
347         return (EDUPL);
348     }
349
350     /*
351      * Remove the record from the chain of deleted records.
352      */
353     remove_from_chain(fcb, recnum);
354
355     /*
356      * Copy new record to the .rec file. 
357      */
358     delflag = FL_RECEXISTS;
359     _cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1); 
360     _cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen); 
361
362     return (ISOK);
363 }
364
365 /*
366  * remvoe_from_chain(fcb, recnum)
367  *
368  * Remove record from the chain of deleted records.
369  */
370
371 static void
372 remove_from_chain(Fcb *fcb, Recno recnum)
373 {
374     char                recnobuf1 [RECNOSIZE] , recnobuf2 [RECNOSIZE];
375     long                pos1, pos2;
376     Recno               recnum2;
377
378     pos1 = _fl_getpos(fcb, recnum);
379     _cp_fromfile(fcb, fcb->datfd, recnobuf1, pos1 + 1, RECNOSIZE); 
380
381     if (fcb->freerecno == recnum) {
382         fcb->freerecno = ldrecno(recnobuf1);
383     }
384     else {
385         recnum2 = fcb->freerecno;
386         do {
387             pos2 = _fl_getpos(fcb, recnum2);
388             _cp_fromfile(fcb, fcb->datfd, recnobuf2, pos2 + 1, RECNOSIZE); 
389             recnum2 = ldrecno(recnobuf2);
390         } while (recnum2 != recnum && recnum2 != NULL_RECNO);
391
392         _cp_tofile(fcb, fcb->datfd, recnobuf1, pos2 + 1, RECNOSIZE); 
393     }
394 }