depend include change.
[idzebra-moved-to-github.git] / dict / drdwr.c
1 #include <sys/types.h>
2 #include <fcntl.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <assert.h>
8
9 #include <dict.h>
10
11 static void pr_lru (Dict_BFile bf)
12 {
13     struct Dict_file_block *p;
14     for (p=bf->lru_back; p; p = p->lru_next)
15     {
16         printf (" %d", p->no);
17     }
18     printf ("\n");
19     fflush (stdout);
20 }
21
22 static struct Dict_file_block *find_block (Dict_BFile bf, int no)
23 {
24     struct Dict_file_block *p;
25
26     for (p=bf->hash_array[no% bf->hash_size]; p; p=p->h_next)
27         if (p->no == no)
28             break;
29     return p;
30 }
31
32 static void release_block (Dict_BFile bf, struct Dict_file_block *p)
33 {
34     assert (p);
35
36     /* remove from lru queue */    
37     if (p->lru_prev)
38         p->lru_prev->lru_next = p->lru_next;
39     else
40         bf->lru_back = p->lru_next;
41     if (p->lru_next)
42         p->lru_next->lru_prev = p->lru_prev;
43     else
44         bf->lru_front = p->lru_prev;
45
46     /* remove from hash chain */
47     *p->h_prev = p->h_next;
48     if (p->h_next)
49         p->h_next->h_prev = p->h_prev;
50
51     /* move to list of free blocks */
52     p->h_next = bf->free_list;
53     bf->free_list = p;
54 }
55
56 void dict_bf_flush_blocks (Dict_BFile bf, int no_to_flush)
57 {
58     struct Dict_file_block *p;
59     int i;
60     for (i=0; i != no_to_flush && bf->lru_back; i++)
61     {
62         p = bf->lru_back;
63         if (p->dirty)
64         {
65             bf_write (bf->bf, p->no, 0, 0, p->data);
66         }
67         release_block (bf, p);
68     }
69 }
70
71 static struct Dict_file_block *alloc_block (Dict_BFile bf, int no)
72 {
73     struct Dict_file_block *p, **pp;
74
75     if (!bf->free_list)
76         dict_bf_flush_blocks (bf, 1);
77     assert (bf->free_list);
78     p = bf->free_list;
79     bf->free_list = p->h_next;
80     p->dirty = 0;
81     p->no = no;
82
83     /* insert at front in lru chain */
84     p->lru_next = NULL;
85     p->lru_prev = bf->lru_front;
86     if (bf->lru_front)
87         bf->lru_front->lru_next = p;
88     else
89         bf->lru_back = p;
90     bf->lru_front = p;
91
92     /* insert in hash chain */
93     pp = bf->hash_array + (no % bf->hash_size);
94     p->h_next = *pp;
95     p->h_prev = pp;
96     if (*pp)
97         (*pp)->h_prev = &p->h_next;
98     *pp = p;
99    
100     return p;
101 }
102
103 static void move_to_front (Dict_BFile bf, struct Dict_file_block *p)
104 {
105     /* Already at front? */
106     if (!p->lru_next)
107         return ;   
108
109     /* Remove */
110     if (p->lru_prev)
111         p->lru_prev->lru_next = p->lru_next;
112     else
113         bf->lru_back = p->lru_next;
114     p->lru_next->lru_prev = p->lru_prev;
115
116     /* Insert at front */
117     p->lru_next = NULL;
118     p->lru_prev = bf->lru_front;
119     if (bf->lru_front)
120         bf->lru_front->lru_next = p;
121     else
122         bf->lru_back = p;
123     bf->lru_front = p;
124 }
125
126 int dict_bf_readp (Dict_BFile bf, int no, void **bufp)
127 {
128     struct Dict_file_block *p;
129     int i;
130     if ((p = find_block (bf, no)))
131     {
132         *bufp = p->data;
133         move_to_front (bf, p);
134         bf->hits++;
135         return 1;
136     }
137     bf->misses++;
138     p = alloc_block (bf, no);
139     i = bf_read (bf->bf, no, 0, 0, p->data);
140     if (i > 0)
141     {
142         *bufp = p->data;
143         return i;
144     }
145     release_block (bf, p);
146     *bufp = NULL;
147     return i;
148 }
149
150 int dict_bf_newp (Dict_BFile dbf, int no, void **bufp)
151 {
152     struct Dict_file_block *p;
153     if (!(p = find_block (dbf, no)))
154         p = alloc_block (dbf, no);
155     else
156         move_to_front (dbf, p);
157     *bufp = p->data;
158     memset (p->data, 0, dbf->block_size);
159     p->dirty = 1;
160 #if 1
161     printf ("bf_newp of %d:", no);
162     pr_lru (dbf);
163 #endif
164     return 1;
165 }
166
167 int dict_bf_touch (Dict_BFile dbf, int no)
168 {
169     struct Dict_file_block *p;
170     if ((p = find_block (dbf, no)))
171     {
172         p->dirty = 1;
173         return 0;
174     }
175     return -1;
176 }
177