~ubuntu-branches/ubuntu/hoary/malaga/hoary

« back to all changes in this revision

Viewing changes to cache.c

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Bushnell, BSG
  • Date: 2004-08-20 12:58:50 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040820125850-rx9s8bn0ep8jgist
Tags: 6.13-4
This should have been urgency=high, because it is an important and
long-delayed accomodation to new upstream with a bajillion bug fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1995 Bjoern Beutel. */
 
2
 
 
3
/* Description. =============================================================*/
 
4
 
 
5
/* Manages the storage of analysis results for faster access. */
 
6
 
 
7
/* Includes. ================================================================*/
 
8
 
 
9
#include <stdio.h>
 
10
#include <stdlib.h>
 
11
#include <string.h>
 
12
#include <setjmp.h>
 
13
#include <stdarg.h>
 
14
#include "basic.h"
 
15
#include "pools.h"
 
16
#include "values.h"
 
17
#include "avl_trees.h"
 
18
#include "cache.h"
 
19
 
 
20
/* Types. ===================================================================*/
 
21
 
 
22
typedef struct cache_entry /* An entry of the cache tree. */
 
23
 
24
  avl_node_t avl_node; /* A node in an AVL tree. */
 
25
  struct cache_entry *prev_ref, *next_ref; /* LRU chain. */
 
26
  string_t surface;
 
27
  int_t fs_count; /* Number of feature structures in fs_vector. */
 
28
  value_t *fs_vector; /* A vector of feature structures. */
 
29
} cache_entry_t;
 
30
 
 
31
/* Global Variables. ========================================================*/
 
32
 
 
33
int_t cache_accesses; /* Number of calls of "word_in_cache". */
 
34
int_t cache_hits; /* Number of successful calls of "word_in_cache". */
 
35
 
 
36
/* Variables. ===============================================================*/
 
37
 
 
38
static cache_entry_t *cache_tree; /* The cache tree. */
 
39
static int_t max_entry_count; /* Maximum of entries in CACHE_TREE. */
 
40
static int_t entry_count; /* Actual number of entries in CACHE_TREE. */
 
41
 
 
42
static cache_entry_t *first_ref; /* The entry that was referenced first. */
 
43
static cache_entry_t *last_ref; /* The entry that was referenced last. */
 
44
 
 
45
/* These are needed for "next_result_in_cache". */
 
46
static cache_entry_t *current_entry;
 
47
static int_t current_result;
 
48
 
 
49
/* Functions. ===============================================================*/
 
50
 
 
51
static int_t 
 
52
compare_cache_entries( avl_node_t *node1, avl_node_t *node2 )
 
53
/* A callback function for "avl_tree_insert", "avl_tree_remove",
 
54
 * used to compare "cache_entry_t" nodes. */
 
55
 
56
  return strcmp( ((cache_entry_t *) node1)->surface, 
 
57
                 ((cache_entry_t *) node2)->surface );
 
58
}
 
59
 
 
60
/*---------------------------------------------------------------------------*/
 
61
 
 
62
static cache_entry_t *
 
63
new_cache_entry( string_t surf_start, string_t surf_end,
 
64
                 int_t fs_count, value_t fs_vector[] )
 
65
/* Create cache entry for string at SURF_START..SURF_END. 
 
66
 * It has FS_COUNT feature structures stored in FS_VECTOR. 
 
67
 * Return the created entry. */
 
68
 
69
  cache_entry_t *cache_entry;
 
70
 
 
71
  /* Allocate a cache entry. */
 
72
  cache_entry = new_mem( sizeof( cache_entry_t ) );
 
73
  cache_entry->surface = new_string( surf_start, surf_end );
 
74
  cache_entry->fs_count = fs_count;
 
75
  cache_entry->fs_vector = fs_vector;
 
76
 
 
77
  entry_count++;
 
78
  return cache_entry;
 
79
}
 
80
 
 
81
/*---------------------------------------------------------------------------*/
 
82
 
 
83
static void 
 
84
free_cache_entry( cache_entry_t **cache_entry )
 
85
/* Free the memory allocated for *CACHE_ENTRY. */
 
86
 
87
  int_t i;
 
88
 
 
89
  if (*cache_entry != NULL) 
 
90
  { 
 
91
    for (i = 0; i < (*cache_entry)->fs_count; i++) 
 
92
      free_mem( &(*cache_entry)->fs_vector[i] );
 
93
    free_mem( &(*cache_entry)->fs_vector );
 
94
    free_mem( &(*cache_entry)->surface );
 
95
    free_mem( cache_entry );
 
96
    entry_count--;
 
97
  }
 
98
}
 
99
 
 
100
/*---------------------------------------------------------------------------*/
 
101
 
 
102
static void 
 
103
reference_entry( cache_entry_t *entry )
 
104
/* Put ENTRY at end of LRU-list if it is not already there. */
 
105
 
106
  if (entry != last_ref) 
 
107
  { 
 
108
    /* Remove entry from old position. */
 
109
    entry->next_ref->prev_ref = entry->prev_ref;
 
110
    if (entry != first_ref) 
 
111
      entry->prev_ref->next_ref = entry->next_ref;
 
112
    else 
 
113
      first_ref = entry->next_ref;
 
114
 
 
115
    /* Enter entry in new position. */
 
116
    entry->prev_ref = last_ref;
 
117
    entry->next_ref = NULL;
 
118
    last_ref->next_ref = entry;
 
119
    last_ref = entry;
 
120
  }
 
121
}
 
122
 
 
123
/*---------------------------------------------------------------------------*/
 
124
 
 
125
bool_t 
 
126
word_in_cache( string_t surf_start, string_t surf_end )
 
127
/* Check if word in [SURF_START..SURF_END]. 
 
128
 * Return TRUE if word found. Use "next_result_in_cache" to get next result. */
 
129
 
130
  cache_entry_t *entry;
 
131
  int_t result;
 
132
 
 
133
  cache_accesses++;
 
134
  entry = cache_tree;
 
135
  while (entry != NULL) 
 
136
  { 
 
137
    result = strncmp( surf_start, entry->surface, surf_end - surf_start );
 
138
    if (result == 0 && entry->surface[ surf_end - surf_start ] != EOS) 
 
139
      result = -1;
 
140
    if (result < 0) 
 
141
      entry = (cache_entry_t *) entry->avl_node.left;
 
142
    else if (result > 0) 
 
143
      entry = (cache_entry_t *) entry->avl_node.right;
 
144
    else /* Word found. */
 
145
    { 
 
146
      reference_entry( entry );
 
147
      current_entry = entry;
 
148
      current_result = 0;
 
149
      cache_hits++;
 
150
      return TRUE;
 
151
    }
 
152
  }
 
153
  return FALSE;
 
154
}
 
155
 
 
156
/*---------------------------------------------------------------------------*/
 
157
 
 
158
value_t 
 
159
next_result_in_cache( void )
 
160
/* Return the next feature structure for the word found by "word_in_cache".
 
161
 * Return NULL if no more feature structure exists. */
 
162
{
 
163
  value_t result;
 
164
 
 
165
  if (current_result >= current_entry->fs_count) 
 
166
    return NULL;
 
167
  result = current_entry->fs_vector[ current_result ];
 
168
  current_result++;
 
169
  return result;
 
170
}
 
171
 
 
172
/*---------------------------------------------------------------------------*/
 
173
 
 
174
static void 
 
175
remove_entry_from_cache( void )
 
176
/* Delete an entry from cache. */
 
177
 
178
  cache_entry_t *entry;
 
179
  
 
180
  /* Remove first element from LRU list. */
 
181
  entry = first_ref;
 
182
  first_ref = entry->next_ref;
 
183
  if (first_ref != NULL) 
 
184
    first_ref->prev_ref = NULL;
 
185
  else 
 
186
    last_ref = NULL;
 
187
 
 
188
  /* Remove ENTRY from tree. */
 
189
  remove_avl_node( (avl_node_t *) entry, (avl_node_t **) &cache_tree, 
 
190
                   compare_cache_entries );
 
191
  free_cache_entry( &entry );
 
192
}
 
193
 
 
194
/*---------------------------------------------------------------------------*/
 
195
 
 
196
void 
 
197
enter_in_cache( string_t surf_start, string_t surf_end,
 
198
                int_t fs_count, value_t fs_vector[] )
 
199
/* Enter the word in [SURF_START..SURF_END] in the cache.
 
200
 * It has FS_COUNT feature structures, stored in FS_VECTOR[].
 
201
 * Be sure that the word is not yet in the cache. */
 
202
 
203
  cache_entry_t *cache_entry;
 
204
 
 
205
  if (entry_count >= max_entry_count) 
 
206
    remove_entry_from_cache();
 
207
  cache_entry = new_cache_entry( surf_start, surf_end, fs_count, fs_vector );
 
208
 
 
209
  /* Enter entry in cache tree. */
 
210
  insert_avl_node( (avl_node_t *) cache_entry, (avl_node_t **) &cache_tree, 
 
211
                   compare_cache_entries );
 
212
 
 
213
  /* Put entry at end of LRU table. */
 
214
  if (last_ref != NULL) 
 
215
    last_ref->next_ref = cache_entry;
 
216
  cache_entry->prev_ref = last_ref;
 
217
  cache_entry->next_ref = NULL;
 
218
  last_ref = cache_entry;
 
219
  if (first_ref == NULL) 
 
220
    first_ref = cache_entry;
 
221
}
 
222
 
 
223
/*---------------------------------------------------------------------------*/
 
224
 
 
225
void 
 
226
clear_cache( void )
 
227
/* Remove all entries from the cache. */
 
228
 
229
  while (entry_count > 0) 
 
230
    remove_entry_from_cache();
 
231
}
 
232
 
 
233
/*---------------------------------------------------------------------------*/
 
234
 
 
235
void 
 
236
set_cache_size( int_t size )
 
237
/* Set maximum number of cache entries to SIZE. */
 
238
 
239
  max_entry_count = size;
 
240
  while (entry_count > max_entry_count) 
 
241
    remove_entry_from_cache();
 
242
}
 
243
 
 
244
/*---------------------------------------------------------------------------*/
 
245
 
 
246
int_t 
 
247
get_cache_size( void )
 
248
/* Get actual number of cache entries. */
 
249
 
250
  return entry_count; 
 
251
}
 
252
 
 
253
/*---------------------------------------------------------------------------*/
 
254
 
 
255
int_t 
 
256
get_cache_maximum( void )
 
257
/* Get maximum number of cache entries. */
 
258
 
259
  return max_entry_count; 
 
260
}
 
261
 
 
262
/* End of file. =============================================================*/