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