Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
292
cde/lib/DtSearch/fileman.c
Normal file
292
cde/lib/DtSearch/fileman.c
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* 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 excede 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 ******************/
|
||||
Reference in New Issue
Block a user