1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/lib/DtSearch/fileman.c
2018-04-28 12:36:44 -06:00

314 lines
8.7 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* COMPONENT_NAME: austext
*
* FUNCTIONS: add_free_space
* find_free_space
* init_header
*
* ORIGINS: 27
*
* (C) COPYRIGHT International Business Machines Corp. 1993,1995
* All Rights Reserved
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/******************* FILEMAN.C **********************
* $XConsortium: fileman.c /main/8 1996/11/25 18:47:12 drk $
* September 1993.
* Garbage collection algorithm: Fileman maintains
* 2 tables at the front of the d99. They keep track of
* small sized 'holes' (unique words that appear only
* once in a record)and large holes of free space.
* Only the N largest holes in each table are saved,
* so some fragmentation still exists. This happens
* particularly when a huge database is built from scratch.
* As the size grows, more and more holes are discarded
* because they are too small to handle any words as
* the database grows. For this reason, mrclean should
* be run at least once after the database grows to a
* fairly good size, to recover the wasted space. Once the
* database reaches its nominal size, the 2 tables are very
* effective at recycling holes, so mrclean need not be
* run for compression purposes.
*
* $Log$
* Revision 2.2 1995/10/24 22:09:25 miker
* Add prolog.
*
* Revision 2.1 1995/09/22 20:05:50 miker
* Freeze DtSearch 0.1, AusText 2.1.8
*
* Revision 1.3 1995/09/05 17:27:37 miker
* Names changes for DtSearch.
*/
#include "SearchP.h"
#include <stdlib.h>
#include <errno.h>
#define PROGNAME "FILEMAN"
#define HOLE_SIZE_LIMIT 500
DtSrINT32 batch_size = 0;
/************************/
/* */
/* Init Header */
/* */
/************************/
/* Initialize file_header data, and write it at the beginning of a new file */
void init_header (FILE * fp, FILE_HEADER * flh)
{
memset (flh, 0, sizeof(FILE_HEADER));
fseek (fp, 0L, SEEK_SET);
fwrite (flh, sizeof(FILE_HEADER), (size_t)1, fp);
return;
} /* init_header() */
/********************************/
/* */
/* fread_d99_header */
/* */
/********************************/
/* Reads d99 header structure from front of passed d99 file.
* Performs byte swap as necessary IN PASSED BUFFER.
* Returns TRUE if successful, else FALSE.
*/
int fread_d99_header (FILE_HEADER *flh, FILE *fp)
{
int i;
errno = 0;
fseek (fp, 0L, SEEK_SET);
if (fread (flh, sizeof(FILE_HEADER), (size_t)1, fp) != 1L)
return FALSE;
NTOHL (flh->hole_count[0]);
NTOHL (flh->hole_count[1]);
for (i = 0; i < NUM_HOLES; i++) {
NTOHL (flh->hole_array[0][i].hole_size);
NTOHL (flh->hole_array[0][i].offset);
NTOHL (flh->hole_array[1][i].hole_size);
NTOHL (flh->hole_array[1][i].offset);
}
return TRUE;
} /* fread_d99_header() */
/********************************/
/* */
/* fwrite_d99_header */
/* */
/********************************/
/* Writes d99 header structure to front of passed d99 file.
* Performs byte swap as necessary IN PASSED BUFFER.
* Returns TRUE if successful, else FALSE.
*/
int fwrite_d99_header (FILE_HEADER *flh, FILE *fp)
{
int i;
HTONL (flh->hole_count[0]);
HTONL (flh->hole_count[1]);
for (i = 0; i < NUM_HOLES; i++) {
HTONL (flh->hole_array[0][i].hole_size);
HTONL (flh->hole_array[0][i].offset);
HTONL (flh->hole_array[1][i].hole_size);
HTONL (flh->hole_array[1][i].offset);
}
errno = 0;
fseek (fp, 0L, SEEK_SET);
if (fwrite (flh, sizeof(FILE_HEADER), (size_t)1, fp) == 1L)
return TRUE;
else
return FALSE;
} /* fwrite_d99_header() */
/************************/
/* */
/* Find Free Space */
/* */
/************************/
/* Find free space that is big enough to hold a new record.
On success - return pointer to the FREE_SPACE_STR.
On failure - return NULL.
*/
FREE_SPACE_STR *find_free_space (DtSrINT32 req_size, FILE_HEADER * flh)
{
static FREE_SPACE_STR space_found;
FREE_SPACE_STR del_rec;
int i, j, k;
DtSrINT32 hole_check_size;
float coeff;
j = -1;
if (req_size <= HOLE_SIZE_LIMIT) {
k = 0;
coeff = 1.1;
}
else {
k = 1;
coeff = 1.2;
}
for (i = 0; i < flh->hole_count[k]; i++) {
if (flh->hole_array[k][i].hole_size >= req_size) {
if (j < 0) {
j = i;
}
else { /** check if it's the smallest one of the
free space available ***/
if (flh->hole_array[k][i].hole_size <
flh->hole_array[k][j].hole_size) {
j = i;
}
}
}
}
/* if big enough free space not found, return NULL */
if (j < 0) {
return NULL;
}
if (flh->hole_array[k][j].hole_size == req_size) {
space_found.hole_size = flh->hole_array[k][j].hole_size;
space_found.offset = flh->hole_array[k][j].offset;
/* compact the hole_array */
if (j == NUM_HOLES - 1) {
(flh->hole_count[k])--;
flh->hole_array[k][j].hole_size = 0;
return &space_found;
}
for (i = j; i < (flh->hole_count[k] - 1); i++) {
flh->hole_array[k][i].hole_size =
flh->hole_array[k][i + 1].hole_size;
flh->hole_array[k][i].offset =
flh->hole_array[k][i + 1].offset;
}
(flh->hole_count[k])--;
}
else {
/* Hole size CAN NOT exceed global batch_size in borodin */
hole_check_size = (req_size * coeff < batch_size) ?
req_size * coeff : batch_size;
if (hole_check_size >= flh->hole_array[k][j].hole_size) {
space_found.hole_size = flh->hole_array[k][j].hole_size;
space_found.offset = flh->hole_array[k][j].offset;
/* compact the hole_array */
if (j == NUM_HOLES - 1) {
flh->hole_array[k][j].hole_size = 0;
}
else {
for (i = j; i < (flh->hole_count[k] - 1); i++) {
flh->hole_array[k][i].hole_size =
flh->hole_array[k][i + 1].hole_size;
flh->hole_array[k][i].offset =
flh->hole_array[k][i + 1].offset;
}
}
(flh->hole_count[k])--;
}
else {
space_found.hole_size = req_size;
space_found.offset = flh->hole_array[k][j].offset;
flh->hole_array[k][j].hole_size -= req_size;
flh->hole_array[k][j].offset += req_size * sizeof(DtSrINT32);
if ((k == 1) &&
(flh->hole_array[k][j].hole_size <= HOLE_SIZE_LIMIT)) {
del_rec.hole_size = flh->hole_array[k][j].hole_size;
del_rec.offset = flh->hole_array[k][j].offset;
add_free_space (&del_rec, flh);
if (j == NUM_HOLES - 1) {
(flh->hole_count[k])--;
flh->hole_array[k][j].hole_size = 0;
return &space_found;
}
for (i = j; i < (flh->hole_count[k] - 1); i++) {
flh->hole_array[k][i].hole_size =
flh->hole_array[k][i + 1].hole_size;
flh->hole_array[k][i].offset =
flh->hole_array[k][i + 1].offset;
}
(flh->hole_count[k])--;
}
}
}
return &space_found;
}
/************ end of function find_free_space ******************/
/************************/
/* */
/* Add Free Space */
/* */
/************************/
/* Adds freed space to the hole_array.
If there'e no space left in the hole_array, checks if the new
space is greater, than the smallest space in the hole_array.
If yes - substitute it.
*/
void add_free_space (FREE_SPACE_STR * del_rec, FILE_HEADER * flh)
{
int i, j, k;
DtSrINT32 min_size;
if (del_rec->hole_size <= HOLE_SIZE_LIMIT) {
k = 0;
}
else {
k = 1;
}
j = flh->hole_count[k];
if (j < NUM_HOLES) {
flh->hole_array[k][j].hole_size = del_rec->hole_size;
flh->hole_array[k][j].offset = del_rec->offset;
(flh->hole_count[k])++;
}
else {
min_size = flh->hole_array[k][0].hole_size;
j = 0;
for (i = 1; i < NUM_HOLES; i++) {
if (flh->hole_array[k][i].hole_size < min_size) {
min_size = flh->hole_array[k][i].hole_size;
j = i;
}
}
if (del_rec->hole_size > flh->hole_array[k][j].hole_size) {
flh->hole_array[k][j].hole_size = del_rec->hole_size;
flh->hole_array[k][j].offset = del_rec->offset;
}
}
return;
}
/************ end of function add_free_space ******************/