IDZEBRA  2.1.2
drdwr.c
Go to the documentation of this file.
1 /* This file is part of the Zebra server.
2  Copyright (C) Index Data
3 
4  Zebra is free software; you can redistribute it and/or modify it under
5  the terms of the GNU General Public License as published by the Free
6  Software Foundation; either version 2, or (at your option) any later
7  version.
8 
9  Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10  WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12  for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 
18 */
19 
20 
21 
22 #if HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <sys/types.h>
26 #include <fcntl.h>
27 #if HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 #include <string.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <assert.h>
34 
35 #include "dict-p.h"
36 
38 {
39  struct Dict_file_block *p;
40  for (p=bf->lru_back; p; p = p->lru_next)
41  {
42  printf(" %d", p->no);
43  }
44  printf("\n");
45  fflush(stdout);
46 }
47 
48 static struct Dict_file_block *find_block(Dict_BFile bf, int no)
49 {
50  struct Dict_file_block *p;
51 
52  for (p=bf->hash_array[no% bf->hash_size]; p; p=p->h_next)
53  if (p->no == no)
54  break;
55  return p;
56 }
57 
58 static void release_block(Dict_BFile bf, struct Dict_file_block *p)
59 {
60  assert(p);
61 
62  /* remove from lru queue */
63  if (p->lru_prev)
64  p->lru_prev->lru_next = p->lru_next;
65  else
66  bf->lru_back = p->lru_next;
67  if (p->lru_next)
68  p->lru_next->lru_prev = p->lru_prev;
69  else
70  bf->lru_front = p->lru_prev;
71 
72  /* remove from hash chain */
73  *p->h_prev = p->h_next;
74  if (p->h_next)
75  p->h_next->h_prev = p->h_prev;
76 
77  /* move to list of free blocks */
78  p->h_next = bf->free_list;
79  bf->free_list = p;
80 }
81 
82 void dict_bf_flush_blocks(Dict_BFile bf, int no_to_flush)
83 {
84  struct Dict_file_block *p;
85  int i;
86  for (i=0; i != no_to_flush && bf->lru_back; i++)
87  {
88  p = bf->lru_back;
89  if (p->dirty)
90  {
91  if (!bf->compact_flag)
92  bf_write(bf->bf, p->no, 0, 0, p->data);
93  else
94  {
95  int effective_block = p->no / bf->block_size;
96  int effective_offset = p->no -
97  effective_block * bf->block_size;
98  int remain = bf->block_size - effective_offset;
99 
100  if (remain >= p->nbytes)
101  {
102  bf_write(bf->bf, effective_block, effective_offset,
103  p->nbytes, p->data);
104 #if 0
105  yaz_log(YLOG_LOG, "bf_write no=%d offset=%d size=%d",
106  effective_block, effective_offset,
107  p->nbytes);
108 #endif
109 
110  }
111  else
112  {
113 #if 0
114  yaz_log(YLOG_LOG, "bf_write1 no=%d offset=%d size=%d",
115  effective_block, effective_offset,
116  remain);
117 #endif
118  bf_write(bf->bf, effective_block, effective_offset,
119  remain, p->data);
120 #if 0
121  yaz_log(YLOG_LOG, "bf_write2 no=%d offset=%d size=%d",
122  effective_block+1, 0, p->nbytes - remain);
123 #endif
124  bf_write(bf->bf, effective_block+1, 0,
125  p->nbytes - remain, (char*)p->data + remain);
126  }
127  }
128  }
129  release_block(bf, p);
130  }
131 }
132 
133 static struct Dict_file_block *alloc_block(Dict_BFile bf, int no)
134 {
135  struct Dict_file_block *p, **pp;
136 
137  if (!bf->free_list)
138  dict_bf_flush_blocks(bf, 1);
139  assert(bf->free_list);
140  p = bf->free_list;
141  bf->free_list = p->h_next;
142  p->dirty = 0;
143  p->no = no;
144 
145  /* insert at front in lru chain */
146  p->lru_next = NULL;
147  p->lru_prev = bf->lru_front;
148  if (bf->lru_front)
149  bf->lru_front->lru_next = p;
150  else
151  bf->lru_back = p;
152  bf->lru_front = p;
153 
154  /* insert in hash chain */
155  pp = bf->hash_array + (no % bf->hash_size);
156  p->h_next = *pp;
157  p->h_prev = pp;
158  if (*pp)
159  (*pp)->h_prev = &p->h_next;
160  *pp = p;
161 
162  return p;
163 }
164 
165 static void move_to_front(Dict_BFile bf, struct Dict_file_block *p)
166 {
167  /* Already at front? */
168  if (!p->lru_next)
169  return ;
170 
171  /* Remove */
172  if (p->lru_prev)
173  p->lru_prev->lru_next = p->lru_next;
174  else
175  bf->lru_back = p->lru_next;
176  p->lru_next->lru_prev = p->lru_prev;
177 
178  /* Insert at front */
179  p->lru_next = NULL;
180  p->lru_prev = bf->lru_front;
181  if (bf->lru_front)
182  bf->lru_front->lru_next = p;
183  else
184  bf->lru_back = p;
185  bf->lru_front = p;
186 }
187 
188 int dict_bf_readp(Dict_BFile bf, int no, void **bufp)
189 {
190  struct Dict_file_block *p;
191  int i;
192  if ((p = find_block(bf, no)))
193  {
194  *bufp = p->data;
195  move_to_front(bf, p);
196  bf->hits++;
197  return 1;
198  }
199  bf->misses++;
200  p = alloc_block(bf, no);
201 
202  if (!bf->compact_flag)
203  i = bf_read(bf->bf, no, 0, 0, p->data);
204  else
205  {
206  int effective_block = no / bf->block_size;
207  int effective_offset = no - effective_block * bf->block_size;
208 
209  i = bf_read(bf->bf, effective_block, effective_offset,
210  bf->block_size - effective_offset, p->data);
211  if (i > 0 && effective_offset > 0)
212  i = bf_read(bf->bf, effective_block+1, 0, effective_offset,
213  (char*) p->data + bf->block_size - effective_offset);
214  i = 1;
215  }
216  if (i > 0)
217  {
218  *bufp = p->data;
219  return i;
220  }
221  release_block(bf, p);
222  *bufp = NULL;
223  return i;
224 }
225 
226 int dict_bf_newp(Dict_BFile dbf, int no, void **bufp, int nbytes)
227 {
228  struct Dict_file_block *p;
229  if (!(p = find_block(dbf, no)))
230  p = alloc_block(dbf, no);
231  else
232  move_to_front(dbf, p);
233  *bufp = p->data;
234  memset(p->data, 0, dbf->block_size);
235  p->dirty = 1;
236  p->nbytes = nbytes;
237 #if 0
238  printf("bf_newp of %d:", no);
239  dict_pr_lru(dbf);
240 #endif
241  return 1;
242 }
243 
245 {
246  struct Dict_file_block *p;
247  if ((p = find_block(dbf, no)))
248  {
249  p->dirty = 1;
250  return 0;
251  }
252  return -1;
253 }
254 
255 /*
256  * Local variables:
257  * c-basic-offset: 4
258  * c-file-style: "Stroustrup"
259  * indent-tabs-mode: nil
260  * End:
261  * vim: shiftwidth=4 tabstop=8 expandtab
262  */
263 
int dict_bf_readp(Dict_BFile bf, int no, void **bufp)
Definition: drdwr.c:188
int compact_flag
Definition: dict-p.h:69
int dict_bf_newp(Dict_BFile dbf, int no, void **bufp, int nbytes)
Definition: drdwr.c:226
struct Dict_file_block * lru_prev
Definition: dict-p.h:46
struct Dict_file_block ** h_prev
Definition: dict-p.h:45
void dict_pr_lru(Dict_BFile bf)
Definition: drdwr.c:37
int block_size
Definition: dict-p.h:66
static void move_to_front(Dict_BFile bf, struct Dict_file_block *p)
Definition: drdwr.c:165
static struct Dict_file_block * find_block(Dict_BFile bf, int no)
Definition: drdwr.c:48
struct Dict_file_block * free_list
Definition: dict-p.h:59
struct Dict_file_block * lru_front
Definition: dict-p.h:62
struct Dict_file_block * h_next
Definition: dict-p.h:45
void * data
Definition: dict-p.h:47
int bf_read(BFile bf, zint no, int offset, int nbytes, void *buf)
read from block file (may call exit)
Definition: bfile.c:319
struct Dict_file_block * lru_back
Definition: dict-p.h:62
struct Dict_file_block * lru_next
Definition: dict-p.h:46
int bf_write(BFile bf, zint no, int offset, int nbytes, const void *buf)
writes block of bytes to file (may call exit)
Definition: bfile.c:346
struct Dict_file_block ** hash_array
Definition: dict-p.h:60
static struct Dict_file_block * alloc_block(Dict_BFile bf, int no)
Definition: drdwr.c:133
static void release_block(Dict_BFile bf, struct Dict_file_block *p)
Definition: drdwr.c:58
void dict_bf_flush_blocks(Dict_BFile bf, int no_to_flush)
Definition: drdwr.c:82
int dict_bf_touch(Dict_BFile dbf, int no)
Definition: drdwr.c:244