2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
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 $ */
29 static char sccsid[] = "@(#)isfixrec.c 1.5 89/07/17 Copyr 1988 Sun Micro";
32 * Copyright (c) 1988 by Sun Microsystems, Inc.
39 * Fixed length record access (FLRA) module.
42 #include "isam_impl.h"
45 long _fl_getpos(); /* Get offset in .rec file */
46 int _fl_deleted(); /* 0/1 returns 1 if record is deleted */
47 static void remove_from_chain(); /* used by _flrec_wrrec() */
50 * _flrec_write(fcb, record, recnum, reclen)
55 * FCB File Control Block
56 * record record buffer
57 * reclen record length (NOT USED)
60 * recnum record number of the new record
62 * Returns 0 if record was written successfully, or -1 if any error.
67 _flrec_write(register Fcb *fcb, char *record, Recno *recnum, int reclen)
71 char delflag = FL_RECEXISTS;
72 char recnobuf [RECNOSIZE];
75 * Reuse a deleted record if one exits.
76 * Otherwise, extend .rec file by a record.
78 if (fcb->freerecno != NULL_RECNO) {
79 recnum2 = fcb->freerecno;
82 * Remove record from the chain of deleted records.
84 rec_position = _fl_getpos(fcb, recnum2); /* Offset in .rec file */
85 _cp_fromfile(fcb, fcb->datfd, recnobuf, rec_position + 1, RECNOSIZE);
86 fcb->freerecno = ldrecno(recnobuf);
89 recnum2 = ++(fcb->lastrecno);
92 * Extend .rec file size if necessary.
94 while (_fl_getpos(fcb, recnum2 + 1) > fcb->datsize * ISPAGESIZE) {
95 fcb->datsize = _extend_file(fcb, fcb->datfd, fcb->datsize);
97 rec_position = _fl_getpos(fcb, recnum2); /* Offset in .rec file */
102 * Copy record to the .at file. Mark record as undeleted.
104 _cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1);
105 _cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen);
113 * _flrec_read(fcb, record, recnum, reclen)
118 * FCB File Control Block
119 * recnum record number of the record
120 * reclen filled with the record size for compatibilty with
121 * variable length records
124 * record record buffer is filled with data
126 * Returns 0 if record was read successfully, or error code if any error.
130 _flrec_read(register Fcb *fcb, char *record, Recno recnum, int *reclen)
136 * Check that recnum is within the range of existing record numbers.
138 if (recnum < 1 || recnum > fcb->lastrecno)
141 rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
144 * Check that the record is not marked as deleted.
146 _cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1);
147 if (delflag == FL_RECDELETED) {
152 * Copy record from the .at file.
154 _cp_fromfile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen);
156 *reclen = fcb->minreclen;
162 * pos = _fl_getpos(fcb, recnum)
164 * Calculate the position of record in .rec file.
168 _fl_getpos(Fcb *fcb, Recno recnum)
170 return ((long)(ISCNTLSIZE + (fcb->minreclen + 1) * (recnum -1)));
174 * _flrec_rewrite(fcb, record, recnum, reclen)
179 * FCB File Control Block
180 * recnum record number of the record
182 * int reclen (NOT USED)
184 * Returns 0 if record was rewritten successfully, or error code if any error.
189 _flrec_rewrite(register Fcb *fcb, char *record, Recno recnum, int reclen)
195 * Check that recnum is within the range of existing record numbers.
197 if (recnum < 1 || recnum > fcb->lastrecno)
200 rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
203 * Check that the record is not marked as deleted.
205 _cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1);
206 if (delflag == FL_RECDELETED) {
211 * Copy new record to the .rec file.
213 _cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen);
219 * _flrec_delete(fcb, recnum)
224 * FCB File Control Block
225 * recnum record number of the record
227 * Returns 0 if record was rewritten successfully, or error code if any error.
231 _flrec_delete(register Fcb *fcb, Recno recnum)
235 char recnobuf [RECNOSIZE];
238 * Check that recnum is within the range of existing record numbers.
240 if (recnum < 1 || recnum > fcb->lastrecno)
243 rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
246 * Check that the record is not marked as deleted.
248 _cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1);
249 if (delflag == FL_RECDELETED) {
254 * Set the delete flag to FL_RECDELETED.
256 delflag = FL_RECDELETED;
257 _cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1);
260 * Insert record into chain of deleted records.
262 strecno(fcb->freerecno, recnobuf);
263 _cp_tofile(fcb, fcb->datfd, recnobuf, rec_position + 1, RECNOSIZE);
264 fcb->freerecno = recnum;
270 * _flrec_wrrec(fcb, record, recnum, reclen)
272 * Write a record by record number.
275 * FCB File Control Block
276 * recnum record number of the record
277 * record record buffer
278 * int reclen (NOT USED)
280 * Returns 0 if record was written successfully, or error code if any error.
282 * Note that _flrec_wrrec() commits updates and syncs the FCB to avoid
283 * buffer pool overflow.
288 _flrec_wrrec(register Fcb *fcb, char *record, Recno recnum, int reclen)
293 char recnumbuf [RECNOSIZE];
296 * Check that recnum is not negative.
301 rec_position = _fl_getpos(fcb, recnum); /* Offset in .rec file */
303 if (recnum > fcb->lastrecno) {
306 * If the recnum is bigger than the highest record number in the .rec
307 * file, extend the .rec file.
309 while (_fl_getpos(fcb, recnum + 1) > fcb->datsize * ISPAGESIZE) {
310 fcb->datsize = _extend_file(fcb, fcb->datfd, fcb->datsize);
312 /* Sync the updates to avoid buffer pool overflow. */
315 (void)_isfcb_cntlpg_w2(fcb);
319 * Mark all records in the range <fcb->lastrecno+1, recnum> as
322 delflag = FL_RECDELETED;
323 for (recnum2 = fcb->lastrecno + 1; recnum2 <= recnum; recnum2++) {
324 _cp_tofile(fcb, fcb->datfd, &delflag, _fl_getpos(fcb, recnum2), 1);
325 strecno(fcb->freerecno, recnumbuf);
326 _cp_tofile(fcb, fcb->datfd, recnumbuf,
327 _fl_getpos(fcb, recnum2) + 1, RECNOSIZE);
328 fcb->freerecno = recnum2;
330 /* Sync the updates to avoid buffer pool overflow. */
333 fcb->lastrecno = recnum;
334 (void)_isfcb_cntlpg_w2(fcb);
338 * Note that the disk structures are in a consistent state now,
339 * the .rec was extended by a few records marked as 'deleted'.
340 * This is important for subsequent rollbacks.
345 * If recnum specifies a record that has existed, check whether it
346 * has been deleted. _flrec_wrrec() does not override existing record.
348 _cp_fromfile(fcb, fcb->datfd, &delflag, rec_position, 1);
349 if (delflag == FL_RECEXISTS) {
354 * Remove the record from the chain of deleted records.
356 remove_from_chain(fcb, recnum);
359 * Copy new record to the .rec file.
361 delflag = FL_RECEXISTS;
362 _cp_tofile(fcb, fcb->datfd, &delflag, rec_position, 1);
363 _cp_tofile(fcb, fcb->datfd, record, rec_position + 1, fcb->minreclen);
369 * remvoe_from_chain(fcb, recnum)
371 * Remove record from the chain of deleted records.
375 remove_from_chain(Fcb *fcb, Recno recnum)
377 char recnobuf1 [RECNOSIZE] , recnobuf2 [RECNOSIZE];
381 pos1 = _fl_getpos(fcb, recnum);
382 _cp_fromfile(fcb, fcb->datfd, recnobuf1, pos1 + 1, RECNOSIZE);
384 if (fcb->freerecno == recnum) {
385 fcb->freerecno = ldrecno(recnobuf1);
388 recnum2 = fcb->freerecno;
390 pos2 = _fl_getpos(fcb, recnum2);
391 _cp_fromfile(fcb, fcb->datfd, recnobuf2, pos2 + 1, RECNOSIZE);
392 recnum2 = ldrecno(recnobuf2);
393 } while (recnum2 != recnum && recnum2 != NULL_RECNO);
395 _cp_tofile(fcb, fcb->datfd, recnobuf1, pos2 + 1, RECNOSIZE);