lib/tt/mini_isam: remove register keyword
[oweals/cde.git] / cde / lib / tt / mini_isam / isdiskbufs2.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                   */
24 /*%%  (c) Copyright 1993, 1994 International Business Machines Corp.     */
25 /*%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                    */
26 /*%%  (c) Copyright 1993, 1994 Novell, Inc.                              */
27 /*%%  $XConsortium: isdiskbufs2.c /main/3 1995/10/23 11:37:47 rswiston $                                                         */
28 #ifndef lint
29 static char sccsid[] = "@(#)isdiskbufs2.c 1.3 89/07/17 Copyr 1988 Sun Micro";
30 #endif
31
32 /*
33  * Copyright (c) 1988 by Sun Microsystems, Inc.
34  */
35
36 /*
37  * _isdiskbufs.c
38  *
39  * Description:
40  *      ISAM disk buffer managament
41  *
42  */
43
44 /************************ NON MAPPED I/O version ***************************/
45
46 #include "isam_impl.h"
47
48 extern struct dlink *_isdln_next(), *_isdln_first();
49
50 #define ISMAXBUFFERS    200                  /* Use 20 buffers */
51 #define ISHASHHDRS      256                  /* Must be a power of two */
52 #define ISHASHMASK      (ISHASHHDRS-1)
53
54 #define __hashblkno(fcb,blkno) (((size_t)(fcb)+(blkno)) & ISHASHMASK)
55
56
57 #define base ((char *)0)
58 #define _isdln_insert(l,e) _isdln_base_insert(base,(l),(e))
59 #define _isdln_append(l,e)  _isdln_base_append(base,(l),(e))
60 #define _isdln_remove(e)  _isdln_base_remove(base,(e))
61 #define _isdln_first(l)  _isdln_base_first(base,(l))
62 #define _isdln_next(l)  _isdln_base_next(base,(l))
63 #define _isdln_prev(l)  _isdln_base_prev(base,(l))
64 #define _isdln_makeempty(l)  _isdln_base_makeempty(base,(l))
65 #define _isdln_isempty(l)  _isdln_base_isempty(base,(l))
66
67 /*---------------------- Local data ---------------------------------------*/
68 static Bufhdr *_getavail(), *_findblock();
69 static void _disk_init(), _commit1buffer(), _rollback1buffer(), _flush1buffer();
70 static void _makenodata();
71
72 Bufhdr bufhdrs [ISMAXBUFFERS];
73 struct dlink  hashhdrs [ISHASHHDRS];         /* Heads of hashed lists */
74
75 struct dlink  availlist;                     /* Available buffer list */
76 struct dlink  *pavail = &availlist;
77
78 struct dlink  changelist;                    /* Change buffer list */
79 struct dlink  *pchangl = &changelist;
80
81 struct dlink  fixlist;                       /* Fixed buffer list */
82 struct dlink  *pfixl = &fixlist;
83
84 static int    availn;                        /* Number of available buffers */
85 static int    minavailn;                     /* Minimum available buffers */
86 static int    maxavailn;                     /* Stop flushing when 
87                                               * when maxavailn buffers
88                                               * are available */
89
90
91 #define ISB_FIXED (ISB_RFIXED | ISB_WFIXED)
92 #define MINAVAILN       40                   /* in procent of total # buffers */
93 #define MAXAVAILN       60                   /* in procent of total # buffers */
94
95
96
97 /* unixfd, .rec, .ind., .var */
98 Bufhdr *
99 _isdisk_fix(Fcb *fcb, int unixfd, Blkno blkno, int mode)
100 {
101     Bufhdr *p, *p2;
102     struct dlink           *hashl;
103
104     /*
105      * Initialize some local data.
106      */
107     _disk_init();       
108
109     if (fcb->datfd == unixfd)
110         assert(blkno != 0);                  /* Never access control page */
111
112     hashl = (hashhdrs +__hashblkno(fcb,blkno));
113     
114     /* Try to find the page in buffer pool. */
115     if ((p = _findblock(fcb, unixfd, blkno)) == NULL) {
116         
117         /* Page is not in the pool - install it. */
118         if (mode != ISFIXNOREAD) {
119             p = _getavail();                 /* Get free page from pool */
120             _isdln_insert(hashl,&p->isb_hash); /* Insert into hash list */
121             
122             _isseekpg(unixfd, blkno);
123             _isreadpg(unixfd, p->isb_buffer);
124
125             p->isb_flags = ISB_READ;
126             p->isb_oldcopy = NULL;
127             p->isb_fcb = fcb;
128             p->isb_unixfd  = unixfd;
129             p->isb_blkno = blkno;
130         }
131         else
132             p = NULL;
133     }   
134     
135     if (p && (p->isb_flags & ISB_FIXED)==0) {
136         
137         /* Remove buffer from pavail (or pchangl) list. */
138         _isdln_remove(&p->isb_aclist);
139
140
141         if (!(p->isb_flags & ISB_CHANGE))
142             availn--;
143
144     }
145     
146     if (mode == ISFIXREAD) {
147         assert(p);
148         
149         if(!(p->isb_flags & ISB_FIXED)) {  
150             
151             /* Add buffer to pfixl list. */
152             _isdln_append(pfixl,&p->isb_flist);
153             p->isb_flags |= ISB_RFIXED;
154             
155         }
156         return (p);
157     }   /* if (p) */
158     else {
159         
160         /* If buffer is already fixed for write, no other actions are necces. */
161         if (p && p->isb_flags & ISB_FIXED) {
162             assert((p->isb_flags & ISB_RFIXED) == 0); /* Buffer cannot be */
163             /* fixed for read when is fixed */
164             /* being fixed for write */
165             return (p);
166         }
167         
168         /* Create shadow page */
169         p2 = _getavail();                    /* Get free page from pool */
170         availn--;
171         _isdln_remove(&p2->isb_aclist);      /* Remove from pavail */
172         _isdln_insert(hashl,&p2->isb_hash);  /* Insert into hash list */
173         _isdln_insert(pfixl,&p2->isb_flist); /* Insert into pfixl list */
174         
175         p2->isb_fcb = fcb;
176         p2->isb_unixfd = unixfd;
177         p2->isb_blkno = blkno;
178         p2->isb_flags = ISB_READ|ISB_WFIXED; /* Mark buffer as dirty */
179         
180         if (mode == ISFIXWRITE)              /* Copy buffer content */
181             memcpy(p2->isb_buffer,p->isb_buffer,ISPAGESIZE);
182         
183         p2->isb_oldcopy = p;
184         
185         /* Make old copy */
186         if (p) {
187             assert ((p->isb_flags & ISB_FIXED) == 0);
188             assert((p->isb_flags & ISB_OLDCOPY) == 0);
189             
190             p->isb_flags |= ISB_OLDCOPY;
191             _isdln_remove(&p->isb_hash);
192         }
193         
194         return (p2);
195     }
196 }
197
198 void
199 _isdisk_unfix (Bufhdr *p)
200 {
201     if (!(p->isb_flags & ISB_FIXED))
202     assert(p->isb_flags & ISB_FIXED);
203     
204     if (p->isb_flags & ISB_WFIXED)           /* Unfix at commit/abort time */
205         return;
206     
207     p->isb_flags &= ~ISB_FIXED;              /* Clear bit */
208     _isdln_remove(&p->isb_flist);            /* Remove from pfixl */
209     
210     /* Append to pavail or pchangl list. */
211     if (p->isb_flags & ISB_CHANGE)
212         _isdln_append(pchangl,&p->isb_aclist); /* Append to pchangl list */
213     else {
214         _isdln_append(pavail,&p->isb_aclist); /* Append to pavail list */
215         availn++;
216     }
217 }
218
219 void
220 _isdisk_commit1 (Bufhdr *p)
221 {
222     _commit1buffer(p);
223 }
224
225 void
226 _isdisk_commit(void)
227 {
228     Bufhdr *p;
229     struct dlink           *e;
230     
231     while ((e = _isdln_first(pfixl)) != pfixl) {
232         p = GETBASE(e,bufhdr,isb_flist);  /* Get pointer to bufhdr */
233         assert(p->isb_flags & ISB_WFIXED);
234         _commit1buffer(p);
235     }
236 }
237
238 void
239 _isdisk_rollback(void)
240 {
241     Bufhdr      *p;
242     struct dlink           *e;
243     
244     while ((e = _isdln_first(pfixl)) != pfixl) {
245         p = GETBASE(e,bufhdr,isb_flist);  /* Get pointer to bufhdr */
246         assert(p->isb_flags & ISB_FIXED);
247         if (p->isb_flags & ISB_WFIXED)
248             _rollback1buffer(p);
249         else 
250             _isdisk_unfix(p);
251     }
252 }
253
254 Bufhdr *
255 _isdisk_refix(Bufhdr *p, int newmode)
256 {
257     Blkno       blkno = p->isb_blkno;
258     Fcb         *fcb = p->isb_fcb;
259     int         unixfd = p->isb_unixfd;
260     
261     assert(newmode == ISFIXWRITE);
262     
263     if (p->isb_flags & ISB_RFIXED) {    
264         _isdisk_unfix(p);
265         return (_isdisk_fix(fcb, unixfd, blkno, ISFIXWRITE));
266     }
267     else
268         return (p);
269 }
270
271 void
272 _isdisk_sync(void)
273 {
274     extern time_t _istimeget();
275     Bufhdr *p;
276     struct dlink           *e;
277     
278     while ((e = _isdln_first(pchangl)) != pchangl) {
279         p = GETBASE(e,bufhdr,isb_aclist);  /* Get pointer to bufhdr */
280         assert(p->isb_flags & ISB_CHANGE);
281         assert((p->isb_flags & ISB_FIXED)==0);
282         _flush1buffer(p);
283     }
284 }
285
286 void
287 _isdisk_inval(void)
288 {
289     extern time_t _istimeget();
290     Bufhdr *p;
291     struct dlink           *e;
292     
293     /* ensure pavail is initialized before using it */
294
295     if (pavail->dln_forward == 0) {
296             _isdln_makeempty(pavail);
297     }
298
299     e = pavail;
300
301     while ((e = _isdln_prev(e)) != pavail) {
302         p = GETBASE(e,bufhdr,isb_aclist);  /* Get pointer to bufhdr */
303     
304         if ((p->isb_flags & ISB_READ) == 0)  
305             break;
306
307         _isdln_remove(&p->isb_hash);
308         p->isb_flags = ISB_NODATA;           /* Mark as no data in the buffer */
309     }
310 }
311
312
313 #if ISDEBUG
314 _isdisk_dumphd(void)
315 {
316     Bufhdr *p;
317     int                     i;
318     
319     (void)printf("\nInd isfd   blkno mode temp oldcopy\n");
320     for (p = bufhdrs, i = 0; i < ISMAXBUFFERS; p++,i++)
321         if (p->isb_flags != ISB_NODATA)
322             (void) printf("%3d: %3d  %6d   %2x     %3d\n",i,
323                           _isfd_getisfd(p->isb_pisfd),
324                           p->isb_blkno,p->isb_flags,
325                           p->isb_oldcopy?(p->isb_oldcopy - bufhdrs):-1);
326 }
327
328 aclistdump(struct dlink *lh)
329 {
330     Bufhdr *p;
331     struct dlink           *e;
332     
333     for (e = _isdln_first(lh); e != lh; e = _isdln_next(e)) {
334         p = GETBASE(e,bufhdr,isb_aclist);  /* Get pointer to bufhdr */
335         (void) printf("%3d: %3d  %6d   %2x     %3d\n",p-bufhdrs,
336                       _isfd_getisfd(p->isb_pisfd),
337                       p->isb_blkno,p->isb_flags,
338                       p->isb_oldcopy?(p->isb_oldcopy - bufhdrs):-1);
339     }
340 }
341
342 flistdump(struct dlink *lh)
343 {
344     Bufhdr *p;
345     struct dlink           *e;
346     
347     for (e = _isdln_first(lh); e != lh; e = _isdln_next(e)) {
348         p = GETBASE(e,bufhdr,isb_flist);  /* Get pointer to bufhdr */
349         (void) printf("%3d: %3d  %6d   %2x     %3d\n",p-bufhdrs,
350                       _isfd_getisfd(p->isb_pisfd),
351                       p->isb_blkno,p->isb_flags,
352                       p->isb_oldcopy?(p->isb_oldcopy - bufhdrs):-1);
353     }
354 }
355
356 #endif
357
358
359 /*------------------------ Local functions ---------------------------------*/
360
361 Static void
362 _disk_init(void)
363 {
364     static Bool  initialized = FALSE;
365     int i;
366     
367     if (initialized == TRUE)
368         return;
369
370     initialized = TRUE;
371     
372     /* Initialize hash queue list heads. */
373     for (i = 0; i < ISHASHHDRS; i++) {
374         _isdln_makeempty(hashhdrs+i);
375     }
376
377     /* initialize pavail, pchangel, and pfixl lists to empty. */
378
379     _isdln_makeempty(pavail);
380     _isdln_makeempty(pchangl);
381     _isdln_makeempty(pfixl);
382     
383     /* Link all buffers into pavail list. */
384     for (i = 0; i < ISMAXBUFFERS; i++) {
385         bufhdrs[i].isb_buffer = _ismalloc(ISPAGESIZE);
386         _isdln_append(pavail,&bufhdrs[i].isb_aclist);
387         availn++;
388     }
389     
390     /* Set maxavailn and minavailn. */
391     minavailn = (ISMAXBUFFERS * MINAVAILN) / 100;
392     maxavailn = (ISMAXBUFFERS * MAXAVAILN) / 100;
393 }
394
395 /* _getavail() - get available buffer in disk */
396 Static Bufhdr *
397 _getavail(void)
398 {
399     Bufhdr *p;
400     struct dlink  *q;
401     
402     if ((q = _isdln_first(pavail)) == pavail) {
403         _isfatal_error("No buffer in pool available");
404     }
405     
406     p = GETBASE(q,bufhdr,isb_aclist);
407     
408     if (p->isb_flags & ISB_READ) {           /* Remove from hash queue */
409         _isdln_remove(&p->isb_hash);
410         p->isb_flags = ISB_NODATA;           /* Mark as no data in the buffer */
411     }
412     
413     return ((Bufhdr *) p);
414 }
415
416 /* _findblock() - Find block in buffer pool */
417 Static Bufhdr *
418 _findblock(Fcb *fcb, int unixfd, Blkno blkno)
419 {
420     Bufhdr *p;
421     struct dlink           *lh, *e;
422     int                    hashval;
423     
424     hashval = __hashblkno(fcb,blkno);
425     
426     lh = hashhdrs + hashval;                 /* lh is list head */
427     for (e = _isdln_first(lh); e != lh; e = _isdln_next(e)) {
428         p = GETBASE(e,bufhdr,isb_hash);  /* Get pointer to bufhdr */
429         if (p->isb_blkno == blkno && p->isb_fcb == fcb && p->isb_unixfd == unixfd) {
430             assert(p->isb_flags != ISB_NODATA); 
431             return(p);
432         }
433     }
434     
435     return (NULL);
436 }
437
438 /* _commit1buffer() - Commit changes to buffer */
439 Static void
440 _commit1buffer(Bufhdr *p)
441 {
442     assert(p->isb_flags & ISB_WFIXED);       /* Fixed for read buffers should */
443     /* go through _isdisk_unfix() */
444     
445     /* Free old permanent buffer if any exists. */
446     if (p->isb_oldcopy) {
447         _makenodata(p->isb_oldcopy);         /* Make this buffer available */
448     }
449     
450     /* Remove buffer from list of fixed buffers. */
451     /* Append buffer to list of changed buffers. */
452     _isdln_remove(&p->isb_flist);
453     _isdln_append(pchangl,&p->isb_aclist);
454     p->isb_flags &= ~ISB_FIXED;
455     p->isb_flags |= ISB_CHANGE;
456 }
457
458 /* _rollback1buffer() - Rollback changes to buffer */
459 Static void
460 _rollback1buffer(Bufhdr *p)
461 {
462     Bufhdr      *p2;
463     
464     assert(p->isb_flags & ISB_WFIXED);       /* Fixed for read buffers should */
465     /* go through _isdisk_unfix() */
466     
467     /* Re-install old copy if that exists. */
468     if ((p2 = p->isb_oldcopy) != NULL) {
469         if (p2->isb_flags & ISB_CHANGE) {
470             _isdln_append(pchangl,&p2->isb_aclist);
471         }
472         else {
473             _isdln_append(pavail,&p2->isb_aclist);
474             availn++;
475         }
476         p2->isb_flags &= ~ISB_OLDCOPY;       /* Clear bit */
477         
478         /* See implementation of _isdln_append() that this will work. */
479         _isdln_append(&p->isb_hash,&p2->isb_hash); /* Insert into hash list */
480     }   
481     
482     
483     _isdln_remove(&p->isb_hash);             /* Remove bufer from hash list */
484     _isdln_remove(&p->isb_flist);            /* Remove bufer from pfixl */
485     _makenodata(p);                          /* Make this buffer available */
486 }
487
488 /* _makenodata() - make buffer available with no data in it*/
489 Static void
490 _makenodata(Bufhdr *p)
491 {
492     assert(p->isb_flags & ISB_READ);
493     
494     p->isb_flags = ISB_NODATA;
495     _isdln_insert(pavail,&p->isb_aclist);
496     availn++;
497 }
498
499 /* _flush1buffer() - flush buffer to disk */
500 Static void
501 _flush1buffer(Bufhdr *p)
502 {
503     assert(p->isb_flags & ISB_CHANGE);
504     
505     _isseekpg(p->isb_unixfd, p->isb_blkno);
506     _iswritepg(p->isb_unixfd, p->isb_buffer);
507     
508     p->isb_flags &= ~ISB_CHANGE;             /* clear change flag */
509     
510     _isdln_remove(&p->isb_aclist);           /* Remove from pchangl */
511     _isdln_append(pavail,&p->isb_aclist);    /* Append to pavail */
512     availn++;
513 }