45015fbaaecd13b257b9d33e9858d17ac0374bd3
[idzebra-moved-to-github.git] / dict / drdwr.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: drdwr.c,v $
7  * Revision 1.9  1997-09-09 13:38:01  adam
8  * Partial port to WIN95/NT.
9  *
10  * Revision 1.8  1995/01/24 11:25:11  adam
11  * Removed stupid assertion.
12  *
13  * Revision 1.7  1994/10/05  10:47:15  adam
14  * Function pr_lru is non-static now. No warning no more.
15  *
16  * Revision 1.6  1994/09/06  13:05:14  adam
17  * Further development of insertion. Some special cases are
18  * not properly handled yet! assert(0) are put here. The
19  * binary search in each page definitely reduce usr CPU.
20  *
21  * Revision 1.5  1994/09/01  17:49:38  adam
22  * Removed stupid line. Work on insertion in dictionary. Not finished yet.
23  *
24  */
25
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #ifndef WINDOWS
29 #include <unistd.h>
30 #endif
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35
36 #include <dict.h>
37
38 void dict_pr_lru (Dict_BFile bf)
39 {
40     struct Dict_file_block *p;
41     for (p=bf->lru_back; p; p = p->lru_next)
42     {
43         printf (" %d", p->no);
44     }
45     printf ("\n");
46     fflush (stdout);
47 }
48
49 static struct Dict_file_block *find_block (Dict_BFile bf, int no)
50 {
51     struct Dict_file_block *p;
52
53     for (p=bf->hash_array[no% bf->hash_size]; p; p=p->h_next)
54         if (p->no == no)
55             break;
56     return p;
57 }
58
59 static void release_block (Dict_BFile bf, struct Dict_file_block *p)
60 {
61     assert (p);
62
63     /* remove from lru queue */    
64     if (p->lru_prev)
65         p->lru_prev->lru_next = p->lru_next;
66     else
67         bf->lru_back = p->lru_next;
68     if (p->lru_next)
69         p->lru_next->lru_prev = p->lru_prev;
70     else
71         bf->lru_front = p->lru_prev;
72
73     /* remove from hash chain */
74     *p->h_prev = p->h_next;
75     if (p->h_next)
76         p->h_next->h_prev = p->h_prev;
77
78     /* move to list of free blocks */
79     p->h_next = bf->free_list;
80     bf->free_list = p;
81 }
82
83 void dict_bf_flush_blocks (Dict_BFile bf, int no_to_flush)
84 {
85     struct Dict_file_block *p;
86     int i;
87     for (i=0; i != no_to_flush && bf->lru_back; i++)
88     {
89         p = bf->lru_back;
90         if (p->dirty)
91         {
92             bf_write (bf->bf, p->no, 0, 0, p->data);
93         }
94         release_block (bf, p);
95     }
96 }
97
98 static struct Dict_file_block *alloc_block (Dict_BFile bf, int no)
99 {
100     struct Dict_file_block *p, **pp;
101
102     if (!bf->free_list)
103         dict_bf_flush_blocks (bf, 1);
104     assert (bf->free_list);
105     p = bf->free_list;
106     bf->free_list = p->h_next;
107     p->dirty = 0;
108     p->no = no;
109
110     /* insert at front in lru chain */
111     p->lru_next = NULL;
112     p->lru_prev = bf->lru_front;
113     if (bf->lru_front)
114         bf->lru_front->lru_next = p;
115     else
116         bf->lru_back = p;
117     bf->lru_front = p;
118
119     /* insert in hash chain */
120     pp = bf->hash_array + (no % bf->hash_size);
121     p->h_next = *pp;
122     p->h_prev = pp;
123     if (*pp)
124         (*pp)->h_prev = &p->h_next;
125     *pp = p;
126    
127     return p;
128 }
129
130 static void move_to_front (Dict_BFile bf, struct Dict_file_block *p)
131 {
132     /* Already at front? */
133     if (!p->lru_next)
134         return ;   
135
136     /* Remove */
137     if (p->lru_prev)
138         p->lru_prev->lru_next = p->lru_next;
139     else
140         bf->lru_back = p->lru_next;
141     p->lru_next->lru_prev = p->lru_prev;
142
143     /* Insert at front */
144     p->lru_next = NULL;
145     p->lru_prev = bf->lru_front;
146     if (bf->lru_front)
147         bf->lru_front->lru_next = p;
148     else
149         bf->lru_back = p;
150     bf->lru_front = p;
151 }
152
153 int dict_bf_readp (Dict_BFile bf, int no, void **bufp)
154 {
155     struct Dict_file_block *p;
156     int i;
157     if ((p = find_block (bf, no)))
158     {
159         *bufp = p->data;
160         move_to_front (bf, p);
161         bf->hits++;
162         return 1;
163     }
164     bf->misses++;
165     p = alloc_block (bf, no);
166     i = bf_read (bf->bf, no, 0, 0, p->data);
167     if (i > 0)
168     {
169         *bufp = p->data;
170         return i;
171     }
172     release_block (bf, p);
173     *bufp = NULL;
174     return i;
175 }
176
177 int dict_bf_newp (Dict_BFile dbf, int no, void **bufp)
178 {
179     struct Dict_file_block *p;
180     if (!(p = find_block (dbf, no)))
181         p = alloc_block (dbf, no);
182     else
183         move_to_front (dbf, p);
184     *bufp = p->data;
185     memset (p->data, 0, dbf->block_size);
186     p->dirty = 1;
187 #if 0
188     printf ("bf_newp of %d:", no);
189     dict_pr_lru (dbf);
190 #endif
191     return 1;
192 }
193
194 int dict_bf_touch (Dict_BFile dbf, int no)
195 {
196     struct Dict_file_block *p;
197     if ((p = find_block (dbf, no)))
198     {
199         p->dirty = 1;
200         return 0;
201     }
202     return -1;
203 }
204