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 1018 /*506*/ /* number of key_ptrs in index block */ 00012 #define level_zero 0 /* level of index leaves */ 00013 #define level_one 1 /* level immediately above leaves */ 00014 #define long_lc sizeof(long) /* lc of a long int */ 00015 #define min_buffer_cnt 8 /* default number of buffers allocated */ 00016 #define max_buffer_cnt 1024 /* max buffers allowed */ 00017 #define buf_hash_load_factor 3 /* hash table is>=this times buffers alloc,*/ 00018 #define max_level 32 /* number of index block levels */ 00019 #define fib_lc 6432 /* length of fixed portion of fib ****hand computed *****/ 00020 #define fib_blocks ((fib_lc-1)/block_lc+1) 00021 /*#define max_segment_lc 4194304 */ /* 1024 blocks of 4096 each */ 00022 #define max_segment_lc max_long /* max length of a file segment */ 00023 #define max_segments 1024 /* max number of file segments */ 00024 #define max_files 10 /* max number of open files */ 00025 #define max_filename_lc 128 /* max length of a file name */ 00026 #define max_extension_lc 40 /* max length of file name extension */ 00027 #define rec_allocation_unit 8 /* user rec allocation unit */ 00028 #define block_allocation_unit 16 /* # blocks to allocate at a time */ 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, /* user, free_lc, or free_rec */ 00075 prefix_lc, /* lc of prefix removed from all keys in block */ 00076 free_block_cnt, /* number of free blocks if on free_block_chain */ 00077 level; /* level of block */ 00078 struct leveln_pntr 00079 next,prev; 00080 struct key_ptr_t /* key_ptrs are inserted from 0, keys and */ 00081 keys[key_ptrs_per_block]; /* file pointers overlay the top end */ 00082 }; 00083 #define ix_block_lc sizeof(struct ix_block) 00084 00085 /* Free space management. Available space is recorded in two separate */ 00086 /* indexes. The first (free_rec_ix) records each space in address */ 00087 /* order using a binary key of segment/sc and lc as the record, The */ 00088 /* second (free_lc_ix) records each space in length order using a */ 00089 /* key of lc/segment/sc. To allocate a record the lc list is */ 00090 /* searched with a key of lc/0/0 then next_rec is used to find a */ 00091 /* space of lc or longer (if it exists). To deallocate, the rec */ 00092 /* list searched and any contiguous entries are combined. */ 00093 00094 typedef union ix_or_freespace_block { 00095 struct ix_block ix; 00096 /* struct freespace_block free;*/ 00097 } block_type_t; 00098 #define block_lc sizeof(block_type_t) 00099 00100 typedef union level0orn_pntr { 00101 struct level0_pntr p0; 00102 struct leveln_pntr pn; 00103 } levelx_pntr; 00104 00105 /*typedef union int_or_byte { 00106 int as_int; 00107 unsigned char as_byte[sizeof(int)]; 00108 } int_alias; 00109 00110 typedef union short_or_byte { 00111 short as_short; 00112 unsigned char as_byte[sizeof(short)]; 00113 } short_alias; 00114 */ 00115 00116 /* Buffer handling. Buffers contain the disk image of an index or */ 00117 /* freespace block */ 00118 /* together with additional information. A hashing technique is */ 00119 /* used to find a buffer that holds a given block. A hash table is */ 00120 /* allocated as the last buffers in the fcb of roughly three times */ 00121 /* the number of buffers allocated. buf_hash_table[k] contains the */ 00122 /* index of the first buffer containing a block whose hash value is */ 00123 /* k. If there are multiple buffers containing blocks with hash */ 00124 /* value k then they are linked using hash_next. */ 00125 00126 struct buffer_type { /* buffer is the memory resident image of */ 00127 /* a disk block */ 00128 unsigned char 00129 lock_cnt, 00130 modified, 00131 notused; 00132 int 00133 older, /* index to prev element in LRU list */ 00134 younger, /* index to next element in LRU list */ 00135 hash_next; 00136 struct leveln_pntr 00137 contents; /* block in buffer, nulln_ptr if empty */ 00138 block_type_t 00139 b; 00140 }; 00141 #define buffer_lc sizeof(struct buffer_type) 00142 #define hash_entries_per_buf (buffer_lc / sizeof(int)) 00143 00144 /* Segment handling. A keyed file consist of one or more component files */ 00145 /* called segments. Segment 0 contains the file information block and */ 00146 /* is alway present. Additional segments are created as needed with */ 00147 /* a suffix of "$n" appended to the base file name where n is the */ 00148 /* segment number. The file information block contains a segment_cnt */ 00149 /* and a list of each segment_length. After open the fcb contains a */ 00150 /* list of the file number on which each segment is open (max_files */ 00151 /* implies not open) in segment_ix */ 00152 00153 /* File handling. Up to max_files files may be open at one time. */ 00154 /* open_file_cnt is the number of files actually open, open_file[] is */ 00155 /* a list of file_indexes in use, file_age[] is the age of each open */ 00156 /* file, open_segment[] is the segment to which the file is open */ 00157 00158 struct fcb { 00159 00160 int 00161 error_code, 00162 version, /* version of keyed file manager */ 00163 segment_cnt, /* number of segments in use */ 00164 primary_level[max_index], /* level of primary index block */ 00165 marker; 00166 boolean 00167 file_ok; 00168 struct leveln_pntr 00169 first_free_block[max_level][max_index],/* points to start of empty block chain */ 00170 first_at_level[max_level][max_index], /* block containing lowest key at level */ 00171 last_pntr[max_level][max_index]; /* last pointer at each level */ 00172 long 00173 segment_length[max_segments];/* length in bytes of each segment */ 00174 00175 /* start of temporary information */ 00176 00177 char 00178 file_name[max_filename_lc], 00179 file_extension[max_extension_lc]; 00180 unsigned char 00181 byte_swapping_required, /* true means swap bytes on I/O */ 00182 trace, /* true means trace execution */ 00183 trace_freespace, /* true means trace space management */ 00184 read_only; /* true means file is read only */ 00185 int 00186 open_file_cnt, /* number of files actually open */ 00187 open_segment[max_files], /* segment to which each file is open */ 00188 file_age[max_files], /* age of each open file */ 00189 oldest_buffer, /* first buffer in LRU buffer list */ 00190 youngest_buffer, /* last buffer in LRU buffer list */ 00191 block_shift; /* log2(block_lc) */ 00192 FILE 00193 *open_file[max_files]; /* pointers to open files */ 00194 00195 int 00196 segment_ix[max_segments], /* index into open_file[] if segment open */ 00197 position_ix[max_index], /* posn. in level0 blk of last retrieval */ 00198 current_age, /* age of file pool (0..maxint)*/ 00199 buffers_allocated, /* number of buffers actually allocated */ 00200 buffers_in_use, /* buffers actually used */ 00201 *buf_hash_table, /* pointer to base of buffer hash table */ 00202 buf_hash_entries; /* size of buf_hash_table */ 00203 struct leveln_pntr 00204 mru_at_level[max_level][max_index], /* most recently used block at each level*/ 00205 position[max_index]; /* level0 block of last retrieval */ 00206 struct buffer_type 00207 buffer[min_buffer_cnt]; /* should be at end of fcb so we can extend */ 00208 }; 00209 #define min_fcb_lc sizeof(struct fcb)