Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / tt / mini_isam / ismngfcb.c
1 /*%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                   */
2 /*%%  (c) Copyright 1993, 1994 International Business Machines Corp.     */
3 /*%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                    */
4 /*%%  (c) Copyright 1993, 1994 Novell, Inc.                              */
5 /*%%  $XConsortium: ismngfcb.c /main/3 1995/10/23 11:42:28 rswiston $                                                    */
6 #ifndef lint
7 static char sccsid[] = "@(#)ismngfcb.c 1.4 89/07/17 Copyr 1988 Sun Micro";
8 #endif
9 /*
10  * Copyright (c) 1988 by Sun Microsystems, Inc.
11  */
12
13 /*
14  * ismngfcb.c
15  *
16  * Description: 
17  *      Manager of open FCB blocks.
18  *
19  * This module keeps track of usage of the FCB blocks and finds a victim
20  * on LRU basis.
21  * It also provides associative access to the FCB by their isfhandles.
22  *
23  */
24 #include "isam_impl.h"
25
26
27 #define FCBHASHSIZE     101                  /* Should be a prime for best hash */
28
29 #if  (MAXFCB_UNIXFD > FCBHASHSIZE)
30 /* 
31  * Cause a syntax error. FCBHASHSIZE must be increased to be > MAXFCB_UNIXFD.
32  * A good estimate is a prime approximately equal (2 * MAXFCB_UNIXFD).
33  */
34 MUST INCREASE FCBHASHSIZE
35 #endif
36
37 struct hashtable {
38     Bytearray   isfhandle;
39     Fcb         *fcb;
40     long        mrused;                      
41 } hashtable [FCBHASHSIZE];
42 #define unused(entry) ((entry).fcb == NULL)
43
44 static int _hashisfhandle();
45
46 static mrused_last = 0;                      /* stamp generator */
47
48
49 /*
50  * _mngfcb_insert(fcb, isfhandle)
51  *
52  * Insert new FCB entry.
53  */
54
55 void
56 _mngfcb_insert(fcb, isfhandle)
57     Fcb         *fcb;
58     Bytearray   *isfhandle;
59 {
60     int                 hashval = _hashisfhandle(isfhandle);
61     register int        ind;
62     int                 ntries;
63
64     /* Try to find an unused entry in the hash table. */
65     ind = hashval;
66     for (ntries = 0; ntries < FCBHASHSIZE; ntries++) {
67         if (unused(hashtable[ind]))
68             break;
69         if (++ind == FCBHASHSIZE)
70             ind = 0;                         /* Wrap the table */
71     }
72
73     if (ntries == FCBHASHSIZE) {
74         _isfatal_error("FCB hash table overflow");
75     }
76         
77     /*
78      * Create an entry at the index ind.
79      * Duplicate the file handle and mark the entry with the current stamp.
80      */
81     hashtable[ind].isfhandle = _bytearr_dup(isfhandle);
82     hashtable[ind].fcb = fcb;
83     hashtable[ind].mrused = mrused_last++;
84 }
85
86
87 /*
88  * fcb = _mngfcb_find(isfhandle)
89  *      
90  * Return a pointer to the FCB, or NULL if the FCB is not found.
91  * If the FCB is found, it is "touched" for the LRU algorithm purpose.
92  */
93
94 Fcb *
95 _mngfcb_find(isfhandle)
96     Bytearray   *isfhandle;
97 {
98     int                 hashval = _hashisfhandle(isfhandle);
99     register int        ind;
100     int                 ntries;
101
102     /* Find the entry. */
103     ind = hashval;
104     for (ntries = 0; ntries < FCBHASHSIZE; ntries++) {
105         if (_bytearr_cmp(&hashtable[ind].isfhandle, isfhandle) == 0)
106             break;
107         if (++ind == FCBHASHSIZE)
108             ind = 0;                         /* Wrap the table */
109     }
110
111     if (ntries == FCBHASHSIZE) {
112         return (NULL);                       /* Not found */
113     } 
114     else {
115
116         /*
117          * Mark the entry with the current stamp.
118          */
119         hashtable[ind].mrused = mrused_last++;
120         return hashtable[ind].fcb;
121     }
122 }
123
124 /*
125  * _mngfcb_delete(isfname)
126  *
127  * Delete an entry.
128  */
129
130 void
131 _mngfcb_delete(isfhandle)
132     Bytearray   *isfhandle;
133 {
134     int                 hashval = _hashisfhandle(isfhandle);
135     register int        ind;
136     int                 ntries;
137
138     /* Find the entry */
139     ind = hashval;
140     for (ntries = 0; ntries < FCBHASHSIZE; ntries++) {
141         if (_bytearr_cmp(&hashtable[ind].isfhandle, isfhandle) == 0)
142             break;
143         if (++ind == FCBHASHSIZE)
144             ind = 0;                         /* Wrap the table */
145     }
146
147     if (ntries == FCBHASHSIZE) {
148         _isfatal_error("_mngfcb_delete cannot find entry");
149     } 
150     else {
151
152         /*
153          * Clear the entry.
154          */
155         _bytearr_free(&hashtable[ind].isfhandle);
156         memset ((char *) &hashtable[ind], 0, sizeof(hashtable[ind]));
157     }
158 }
159
160
161 /*
162  * isfhandle = _mngfcb_victim()
163  *
164  * Find LRU used FCB.
165  */
166
167 Bytearray *
168 _mngfcb_victim()
169 {
170     int                 victim_ind = -1;
171     long                victim_time = 0;     /* Assign to shut up lint */
172     register int        i;
173
174     for (i = 0; i < FCBHASHSIZE; i++) {
175
176         if (unused(hashtable[i]))            /* Skip empty slots in table */
177             continue;
178         
179         if (victim_ind == -1 || victim_time > hashtable[i].mrused) {    
180             victim_ind = i;
181             victim_time = hashtable[i].mrused;
182         }
183     }
184     return ((victim_ind == -1) ? NULL : &hashtable[victim_ind].isfhandle);
185 }
186
187
188 /*
189  * _hashisfhandle(isfhandle)
190  *
191  * Hash isfhandle into an integer.
192  */
193
194 Static int
195 _hashisfhandle(isfhandle)
196     Bytearray           *isfhandle;
197 {
198     register char       *p;
199     register unsigned   h, g;
200     register int        len;
201
202     len = isfhandle->length;
203     p = isfhandle->data;
204     h = 0;
205
206     while (len-- > 0) {
207         h = (h << 4) + (*p++);
208         if (g = h&0xf0000000) {
209             h = h ^ (g >> 24);
210             h = h ^ g;
211         }
212     }
213     return (h % FCBHASHSIZE);
214 }