2
0

isfixrec.c 9.7 KB

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