00001 00002 /* */ 00003 /* Copyright 1984,1985,1986,1988,1989,1990,2003,2004 by Howard Turtle */ 00004 /* */ 00005 00006 #define max_long 2147483647 00007 #define keyf 32472 /* marker for fcb */ 00008 #define current_version 5 /* version of keyed file software */ 00009 #define maxkey_lc 512 /* maximum key length */ 00010 #define max_prefix_lc 255 00011 #define key_ptrs_per_block 506 /* number of key_ptrs in index block */ 00012 #define random_split_lc 880 /* chars to be freed on random split */ 00013 #define level_zero 0 /* level of index leaves */ 00014 #define level_one 1 /* level immediately above leaves */ 00015 #define long_lc sizeof(long) /* lc of a long int */ 00016 #define min_buffer_cnt 4 /* default number of buffers allocated */ 00017 #define max_buffer_cnt 1024 /* max buffers allowed */ 00018 #define buf_hash_load_factor 3 /* hash table is>=this times buffers alloc,*/ 00019 #define max_level 32 /* number of index block levels */ 00020 /* fib_lc is set to size of fcb minus buffers and segment_ix table */ 00021 /* it's still longer than it needs to be */ 00022 #define fib_lc min_fcb_lc-(min_buffer_cnt*buffer_lc)-(max_segments*sizeof(int)) 00023 #define max_segment_lc max_long /* max length of a file segment */ 00024 #define max_segments 1024 /* max number of file segments */ 00025 #define max_files 10 /* max number of open files */ 00026 #define max_filename_lc 128 /* max length of a file name */ 00027 #define max_extension_lc 40 /* max length of file name extension */ 00028 #define rec_allocation_unit 8 /* user rec allocation unit */ 00029 #define user_ix 0 00030 #define free_rec_ix 1 00031 #define free_lc_ix 2 00032 #define max_index 3 00033 00034 enum comparison {less,equal,greater}; 00035 00036 struct key { 00037 unsigned char 00038 text[maxkey_lc]; 00039 short 00040 lc; 00041 }; 00042 00043 struct leveln_pntr{ 00044 int 00045 segment; 00046 unsigned long 00047 block; 00048 }; 00049 #define leveln_lc sizeof(struct leveln_pntr) 00050 00051 struct level0_pntr { 00052 int 00053 segment; 00054 unsigned long 00055 sc, 00056 lc; 00057 }; 00058 #define level0_lc sizeof(struct level0_pntr) 00059 00060 struct key_ptr_t { 00061 short 00062 sc, /* start character of key */ 00063 lc; /* lc of key, does not include pointer */ 00064 }; 00065 #define key_ptr_lc sizeof(struct key_ptr_t) 00066 #define keyspace_lc (key_ptr_lc*key_ptrs_per_block) 00067 00068 struct ix_block { /* block is the disk resident image of */ 00069 short /* an index block */ 00070 keys_in_block, 00071 chars_in_use; /* chars in key/pointer pool, does not */ 00072 /* include length of key_ptr_t entries */ 00073 unsigned char 00074 index_type, 00075 prefix_lc, 00076 level; 00077 struct leveln_pntr 00078 next,prev; 00079 struct key_ptr_t /* key_ptrs are inserted from 0, keys and */ 00080 keys[key_ptrs_per_block]; /* file pointers overlay the top end */ 00081 }; 00082 #define ix_block_lc sizeof(struct ix_block) 00083 00084 /* Free space management. Available space is recorded in two separate */ 00085 /* indexes. The first (free_rec_ix) records each space in address */ 00086 /* order using a binary key of segment/sc and lc as the record, The */ 00087 /* second (free_lc_ix) records each space in length order using a */ 00088 /* key of lc/segment/sc. To allocate a record the lc list is */ 00089 /* searched with a key of lc/0/0 then next_rec is used to find a */ 00090 /* space of lc or longer (if it exists). To deallocate, the rec */ 00091 /* list searched and any contiguous entries are combined. */ 00092 00093 typedef union ix_or_freespace_block { 00094 struct ix_block ix; 00095 /* struct freespace_block free;*/ 00096 } block_type_t; 00097 #define block_lc sizeof(block_type_t) 00098 00099 typedef union level0orn_pntr { 00100 struct level0_pntr p0; 00101 struct leveln_pntr pn; 00102 } levelx_pntr; 00103 00104 00105 /* Buffer handling. Buffers contain the disk image of an index or */ 00106 /* freespace block */ 00107 /* together with additional information. A hashing technique is */ 00108 /* used to find a buffer that holds a given block. A hash table is */ 00109 /* allocated as the last buffers in the fcb of roughly three times */ 00110 /* the number of buffers allocated. buf_hash_table[k] contains the */ 00111 /* index of the first buffer containing a block whose hash value is */ 00112 /* k. If there are multiple buffers containing blocks with hash */ 00113 /* value k then they are linked using hash_next. */ 00114 00115 struct buffer_type { /* buffer is the memory resident image of */ 00116 /* a disk block */ 00117 unsigned char 00118 locked, 00119 modified, 00120 notused; 00121 int 00122 older, /* index to prev element in LRU list */ 00123 younger, /* index to next element in LRU list */ 00124 hash_next; 00125 struct leveln_pntr 00126 contents; /* block in buffer, nulln_ptr if empty */ 00127 block_type_t 00128 b; 00129 }; 00130 #define buffer_lc sizeof(struct buffer_type) 00131 #define hash_entries_per_buf (buffer_lc / sizeof(int)) 00132 00133 /* Segment handling. A keyed file consist of one or more component files */ 00134 /* called segments. Segment 0 contains the file information block and */ 00135 /* is alway present. Additional segments are created as needed with */ 00136 /* a suffix of "$n" appended to the base file name where n is the */ 00137 /* segment number. The file information block contains a segment_cnt */ 00138 /* and a list of each segment_length. After open the fcb contains a */ 00139 /* list of the file number on which each segment is open (max_files */ 00140 /* implies not open) in segment_ix */ 00141 00142 /* File handling. Up to max_files files may be open at one time. */ 00143 /* open_file_cnt is the number of files actually open, open_file[] is */ 00144 /* a list of file_indexes in use, file_age[] is the age of each open */ 00145 /* file, open_segment[] is the segment to which the file is open */ 00146 00147 struct fcb { 00148 00149 int 00150 error_code, 00151 version, /* version of keyed file manager */ 00152 segment_cnt, /* number of segments in use */ 00153 primary_level[max_index], /* level of primary index block */ 00154 marker; 00155 boolean 00156 file_ok; 00157 struct leveln_pntr 00158 first_at_level[max_level][max_index], /* block containing lowest key at level */ 00159 last_pntr[max_level][max_index]; /* last pointer at each level */ 00160 long 00161 segment_length[max_segments];/* length in bytes of each segment */ 00162 00163 /* start of temporary information */ 00164 00165 char 00166 file_name[max_filename_lc], 00167 file_extension[max_extension_lc]; 00168 unsigned char 00169 trace, /* true means trace execution */ 00170 trace_freespace; 00171 int 00172 open_file_cnt, /* number of files actually open */ 00173 open_segment[max_files], /* segment to which each file is open */ 00174 file_age[max_files], /* age of each open file */ 00175 oldest_buffer, /* first buffer in LRU buffer list */ 00176 youngest_buffer; /* last buffer in LRU buffer list */ 00177 FILE 00178 *open_file[max_files]; /* pointers to open files */ 00179 00180 int 00181 segment_ix[max_segments], /* index into open_file[] if segment open */ 00182 position_ix[max_index], /* posn. in level0 blk of last retrieval */ 00183 current_age, /* age of file pool (0..maxint)*/ 00184 buffers_allocated, /* number of buffers actually allocated */ 00185 buffers_in_use, /* buffers actually used */ 00186 *buf_hash_table, /* pointer to base of buffer hash table */ 00187 buf_hash_entries; /* size of buf_hash_table */ 00188 struct leveln_pntr 00189 mru_at_level[max_level][max_index], /* most recently used block at each level*/ 00190 position[max_index]; /* level0 block of last retrieval */ 00191 struct buffer_type 00192 buffer[min_buffer_cnt]; /* should be at end of fcb so we can extend */ 00193 }; 00194 #define min_fcb_lc sizeof(struct fcb)