fileman.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. /*
  24. * COMPONENT_NAME: austext
  25. *
  26. * FUNCTIONS: add_free_space
  27. * find_free_space
  28. * init_header
  29. *
  30. * ORIGINS: 27
  31. *
  32. * (C) COPYRIGHT International Business Machines Corp. 1993,1995
  33. * All Rights Reserved
  34. * US Government Users Restricted Rights - Use, duplication or
  35. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  36. */
  37. /******************* FILEMAN.C **********************
  38. * $XConsortium: fileman.c /main/8 1996/11/25 18:47:12 drk $
  39. * September 1993.
  40. * Garbage collection algorithm: Fileman maintains
  41. * 2 tables at the front of the d99. They keep track of
  42. * small sized 'holes' (unique words that appear only
  43. * once in a record)and large holes of free space.
  44. * Only the N largest holes in each table are saved,
  45. * so some fragmentation still exists. This happens
  46. * particularly when a huge database is built from scratch.
  47. * As the size grows, more and more holes are discarded
  48. * because they are too small to handle any words as
  49. * the database grows. For this reason, mrclean should
  50. * be run at least once after the database grows to a
  51. * fairly good size, to recover the wasted space. Once the
  52. * database reaches its nominal size, the 2 tables are very
  53. * effective at recycling holes, so mrclean need not be
  54. * run for compression purposes.
  55. *
  56. * $Log$
  57. * Revision 2.2 1995/10/24 22:09:25 miker
  58. * Add prolog.
  59. *
  60. * Revision 2.1 1995/09/22 20:05:50 miker
  61. * Freeze DtSearch 0.1, AusText 2.1.8
  62. *
  63. * Revision 1.3 1995/09/05 17:27:37 miker
  64. * Names changes for DtSearch.
  65. */
  66. #include "SearchP.h"
  67. #include <stdlib.h>
  68. #include <errno.h>
  69. #define PROGNAME "FILEMAN"
  70. #define HOLE_SIZE_LIMIT 500
  71. DtSrINT32 batch_size = 0;
  72. /************************/
  73. /* */
  74. /* Init Header */
  75. /* */
  76. /************************/
  77. /* Initialize file_header data, and write it at the beginning of a new file */
  78. void init_header (FILE * fp, FILE_HEADER * flh)
  79. {
  80. memset (flh, 0, sizeof(FILE_HEADER));
  81. fseek (fp, 0L, SEEK_SET);
  82. fwrite (flh, sizeof(FILE_HEADER), (size_t)1, fp);
  83. return;
  84. } /* init_header() */
  85. /********************************/
  86. /* */
  87. /* fread_d99_header */
  88. /* */
  89. /********************************/
  90. /* Reads d99 header structure from front of passed d99 file.
  91. * Performs byte swap as necessary IN PASSED BUFFER.
  92. * Returns TRUE if successful, else FALSE.
  93. */
  94. int fread_d99_header (FILE_HEADER *flh, FILE *fp)
  95. {
  96. int i;
  97. errno = 0;
  98. fseek (fp, 0L, SEEK_SET);
  99. if (fread (flh, sizeof(FILE_HEADER), (size_t)1, fp) != 1L)
  100. return FALSE;
  101. NTOHL (flh->hole_count[0]);
  102. NTOHL (flh->hole_count[1]);
  103. for (i = 0; i < NUM_HOLES; i++) {
  104. NTOHL (flh->hole_array[0][i].hole_size);
  105. NTOHL (flh->hole_array[0][i].offset);
  106. NTOHL (flh->hole_array[1][i].hole_size);
  107. NTOHL (flh->hole_array[1][i].offset);
  108. }
  109. return TRUE;
  110. } /* fread_d99_header() */
  111. /********************************/
  112. /* */
  113. /* fwrite_d99_header */
  114. /* */
  115. /********************************/
  116. /* Writes d99 header structure to front of passed d99 file.
  117. * Performs byte swap as necessary IN PASSED BUFFER.
  118. * Returns TRUE if successful, else FALSE.
  119. */
  120. int fwrite_d99_header (FILE_HEADER *flh, FILE *fp)
  121. {
  122. int i;
  123. HTONL (flh->hole_count[0]);
  124. HTONL (flh->hole_count[1]);
  125. for (i = 0; i < NUM_HOLES; i++) {
  126. HTONL (flh->hole_array[0][i].hole_size);
  127. HTONL (flh->hole_array[0][i].offset);
  128. HTONL (flh->hole_array[1][i].hole_size);
  129. HTONL (flh->hole_array[1][i].offset);
  130. }
  131. errno = 0;
  132. fseek (fp, 0L, SEEK_SET);
  133. if (fwrite (flh, sizeof(FILE_HEADER), (size_t)1, fp) == 1L)
  134. return TRUE;
  135. else
  136. return FALSE;
  137. } /* fwrite_d99_header() */
  138. /************************/
  139. /* */
  140. /* Find Free Space */
  141. /* */
  142. /************************/
  143. /* Find free space that is big enough to hold a new record.
  144. On success - return pointer to the FREE_SPACE_STR.
  145. On failure - return NULL.
  146. */
  147. FREE_SPACE_STR *find_free_space (DtSrINT32 req_size, FILE_HEADER * flh)
  148. {
  149. static FREE_SPACE_STR space_found;
  150. FREE_SPACE_STR del_rec;
  151. int i, j, k;
  152. DtSrINT32 hole_check_size;
  153. float coeff;
  154. j = -1;
  155. if (req_size <= HOLE_SIZE_LIMIT) {
  156. k = 0;
  157. coeff = 1.1;
  158. }
  159. else {
  160. k = 1;
  161. coeff = 1.2;
  162. }
  163. for (i = 0; i < flh->hole_count[k]; i++) {
  164. if (flh->hole_array[k][i].hole_size >= req_size) {
  165. if (j < 0) {
  166. j = i;
  167. }
  168. else { /** check if it's the smallest one of the
  169. free space available ***/
  170. if (flh->hole_array[k][i].hole_size <
  171. flh->hole_array[k][j].hole_size) {
  172. j = i;
  173. }
  174. }
  175. }
  176. }
  177. /* if big enough free space not found, return NULL */
  178. if (j < 0) {
  179. return NULL;
  180. }
  181. if (flh->hole_array[k][j].hole_size == req_size) {
  182. space_found.hole_size = flh->hole_array[k][j].hole_size;
  183. space_found.offset = flh->hole_array[k][j].offset;
  184. /* compact the hole_array */
  185. if (j == NUM_HOLES - 1) {
  186. (flh->hole_count[k])--;
  187. flh->hole_array[k][j].hole_size = 0;
  188. return &space_found;
  189. }
  190. for (i = j; i < (flh->hole_count[k] - 1); i++) {
  191. flh->hole_array[k][i].hole_size =
  192. flh->hole_array[k][i + 1].hole_size;
  193. flh->hole_array[k][i].offset =
  194. flh->hole_array[k][i + 1].offset;
  195. }
  196. (flh->hole_count[k])--;
  197. }
  198. else {
  199. /* Hole size CAN NOT exceed global batch_size in borodin */
  200. hole_check_size = (req_size * coeff < batch_size) ?
  201. req_size * coeff : batch_size;
  202. if (hole_check_size >= flh->hole_array[k][j].hole_size) {
  203. space_found.hole_size = flh->hole_array[k][j].hole_size;
  204. space_found.offset = flh->hole_array[k][j].offset;
  205. /* compact the hole_array */
  206. if (j == NUM_HOLES - 1) {
  207. flh->hole_array[k][j].hole_size = 0;
  208. }
  209. else {
  210. for (i = j; i < (flh->hole_count[k] - 1); i++) {
  211. flh->hole_array[k][i].hole_size =
  212. flh->hole_array[k][i + 1].hole_size;
  213. flh->hole_array[k][i].offset =
  214. flh->hole_array[k][i + 1].offset;
  215. }
  216. }
  217. (flh->hole_count[k])--;
  218. }
  219. else {
  220. space_found.hole_size = req_size;
  221. space_found.offset = flh->hole_array[k][j].offset;
  222. flh->hole_array[k][j].hole_size -= req_size;
  223. flh->hole_array[k][j].offset += req_size * sizeof(DtSrINT32);
  224. if ((k == 1) &&
  225. (flh->hole_array[k][j].hole_size <= HOLE_SIZE_LIMIT)) {
  226. del_rec.hole_size = flh->hole_array[k][j].hole_size;
  227. del_rec.offset = flh->hole_array[k][j].offset;
  228. add_free_space (&del_rec, flh);
  229. if (j == NUM_HOLES - 1) {
  230. (flh->hole_count[k])--;
  231. flh->hole_array[k][j].hole_size = 0;
  232. return &space_found;
  233. }
  234. for (i = j; i < (flh->hole_count[k] - 1); i++) {
  235. flh->hole_array[k][i].hole_size =
  236. flh->hole_array[k][i + 1].hole_size;
  237. flh->hole_array[k][i].offset =
  238. flh->hole_array[k][i + 1].offset;
  239. }
  240. (flh->hole_count[k])--;
  241. }
  242. }
  243. }
  244. return &space_found;
  245. }
  246. /************ end of function find_free_space ******************/
  247. /************************/
  248. /* */
  249. /* Add Free Space */
  250. /* */
  251. /************************/
  252. /* Adds freed space to the hole_array.
  253. If there'e no space left in the hole_array, checks if the new
  254. space is greater, than the smallest space in the hole_array.
  255. If yes - substitute it.
  256. */
  257. void add_free_space (FREE_SPACE_STR * del_rec, FILE_HEADER * flh)
  258. {
  259. int i, j, k;
  260. DtSrINT32 min_size;
  261. if (del_rec->hole_size <= HOLE_SIZE_LIMIT) {
  262. k = 0;
  263. }
  264. else {
  265. k = 1;
  266. }
  267. j = flh->hole_count[k];
  268. if (j < NUM_HOLES) {
  269. flh->hole_array[k][j].hole_size = del_rec->hole_size;
  270. flh->hole_array[k][j].offset = del_rec->offset;
  271. (flh->hole_count[k])++;
  272. }
  273. else {
  274. min_size = flh->hole_array[k][0].hole_size;
  275. j = 0;
  276. for (i = 1; i < NUM_HOLES; i++) {
  277. if (flh->hole_array[k][i].hole_size < min_size) {
  278. min_size = flh->hole_array[k][i].hole_size;
  279. j = i;
  280. }
  281. }
  282. if (del_rec->hole_size > flh->hole_array[k][j].hole_size) {
  283. flh->hole_array[k][j].hole_size = del_rec->hole_size;
  284. flh->hole_array[k][j].offset = del_rec->offset;
  285. }
  286. }
  287. return;
  288. }
  289. /************ end of function add_free_space ******************/