Blame cache.c

Packit d394d9
/* Copyright (C) 1996 Bjoern Beutel. */
Packit d394d9
Packit d394d9
/* Description. =============================================================*/
Packit d394d9
Packit d394d9
/* Manages the storage of analysis results for faster access. */
Packit d394d9
Packit d394d9
/* Includes. ================================================================*/
Packit d394d9
Packit d394d9
#include <stdio.h>
Packit d394d9
#include <stdlib.h>
Packit d394d9
#include <string.h>
Packit d394d9
#include <setjmp.h>
Packit d394d9
#include <stdarg.h>
Packit d394d9
#include <glib.h>
Packit d394d9
#include "basic.h"
Packit d394d9
#include "pools.h"
Packit d394d9
#include "values.h"
Packit d394d9
#include "avl_trees.h"
Packit d394d9
#include "cache.h"
Packit d394d9
Packit d394d9
/* Types. ===================================================================*/
Packit d394d9
Packit d394d9
typedef struct cache_entry /* An entry of the cache tree. */
Packit d394d9
{ 
Packit d394d9
  avl_node_t avl_node; /* A node in an AVL tree. */
Packit d394d9
  struct cache_entry *prev_ref, *next_ref; /* LRU chain. */
Packit d394d9
  string_t surface;
Packit d394d9
  int_t feat_count; /* Number of feature structures in feat_vector. */
Packit d394d9
  value_t *feat_vector; /* A vector of feature structures. */
Packit d394d9
} cache_entry_t;
Packit d394d9
Packit d394d9
/* Global Variables. ========================================================*/
Packit d394d9
Packit d394d9
int_t cache_accesses; /* Number of calls of "word_in_cache". */
Packit d394d9
int_t cache_hits; /* Number of successful calls of "word_in_cache". */
Packit d394d9
Packit d394d9
/* Variables. ===============================================================*/
Packit d394d9
Packit d394d9
static avl_node_t *cache_tree; /* The cache tree. Actually points to 
Packit d394d9
				* cache_entry_t. */
Packit d394d9
static int_t max_entry_count; /* Maximum of entries in CACHE_TREE. */
Packit d394d9
static int_t entry_count; /* Actual number of entries in CACHE_TREE. */
Packit d394d9
Packit d394d9
static cache_entry_t *first_ref; /* The entry that was referenced first. */
Packit d394d9
static cache_entry_t *last_ref; /* The entry that was referenced last. */
Packit d394d9
Packit d394d9
/* These are needed for "next_result_in_cache". */
Packit d394d9
static cache_entry_t *current_entry;
Packit d394d9
static int_t current_result;
Packit d394d9
Packit d394d9
/* Functions. ===============================================================*/
Packit d394d9
Packit d394d9
static int_t 
Packit d394d9
compare_cache_entries( avl_node_t *node1, avl_node_t *node2 )
Packit d394d9
/* A callback function for "avl_tree_insert", "avl_tree_remove",
Packit d394d9
 * used to compare "cache_entry_t" nodes. */
Packit d394d9
{ 
Packit d394d9
  return strcmp( ((cache_entry_t *) node1)->surface, 
Packit d394d9
                 ((cache_entry_t *) node2)->surface );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static cache_entry_t *
Packit d394d9
new_cache_entry( string_t surf_start, string_t surf_end,
Packit d394d9
                 int_t feat_count, value_t feat_vector[] )
Packit d394d9
/* Create cache entry for string at SURF_START..SURF_END. 
Packit d394d9
 * It has FEAT_COUNT feature structures stored in FEAT_VECTOR. 
Packit d394d9
 * Return the created entry. */
Packit d394d9
{ 
Packit d394d9
  cache_entry_t *cache_entry;
Packit d394d9
Packit d394d9
  /* Allocate a cache entry. */
Packit d394d9
  cache_entry = new_mem( sizeof( cache_entry_t ) );
Packit d394d9
  cache_entry->surface = new_string( surf_start, surf_end );
Packit d394d9
  cache_entry->feat_count = feat_count;
Packit d394d9
  cache_entry->feat_vector = feat_vector;
Packit d394d9
Packit d394d9
  entry_count++;
Packit d394d9
  return cache_entry;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
free_cache_entry( cache_entry_t **cache_entry )
Packit d394d9
/* Free the memory allocated for *CACHE_ENTRY. */
Packit d394d9
{ 
Packit d394d9
  int_t i;
Packit d394d9
Packit d394d9
  if (*cache_entry != NULL) 
Packit d394d9
  { 
Packit d394d9
    for (i = 0; i < (*cache_entry)->feat_count; i++) 
Packit d394d9
      free_mem( &(*cache_entry)->feat_vector[i] );
Packit d394d9
    free_mem( &(*cache_entry)->feat_vector );
Packit d394d9
    free_mem( &(*cache_entry)->surface );
Packit d394d9
    free_mem( cache_entry );
Packit d394d9
    entry_count--;
Packit d394d9
  }
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
reference_entry( cache_entry_t *entry )
Packit d394d9
/* Put ENTRY at end of LRU-list if it is not already there. */
Packit d394d9
{ 
Packit d394d9
  if (entry != last_ref) 
Packit d394d9
  { 
Packit d394d9
    /* Remove entry from old position. */
Packit d394d9
    entry->next_ref->prev_ref = entry->prev_ref;
Packit d394d9
    if (entry != first_ref) 
Packit d394d9
      entry->prev_ref->next_ref = entry->next_ref;
Packit d394d9
    else 
Packit d394d9
      first_ref = entry->next_ref;
Packit d394d9
Packit d394d9
    /* Enter entry in new position. */
Packit d394d9
    entry->prev_ref = last_ref;
Packit d394d9
    entry->next_ref = NULL;
Packit d394d9
    last_ref->next_ref = entry;
Packit d394d9
    last_ref = entry;
Packit d394d9
  }
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
bool_t 
Packit d394d9
word_in_cache( string_t surf_start, string_t surf_end )
Packit d394d9
/* Check if word in [SURF_START..SURF_END] is in the cache. 
Packit d394d9
 * Return TRUE if word found. Use "next_result_in_cache" to get next result. */
Packit d394d9
{ 
Packit d394d9
  cache_entry_t *entry;
Packit d394d9
  int_t result;
Packit d394d9
Packit d394d9
  cache_accesses++;
Packit d394d9
  entry = (cache_entry_t *) cache_tree;
Packit d394d9
  while (entry != NULL) 
Packit d394d9
  { 
Packit d394d9
    result = strncmp( surf_start, entry->surface, surf_end - surf_start );
Packit d394d9
    if (result == 0 && entry->surface[ surf_end - surf_start ] != EOS) 
Packit d394d9
      result = -1;
Packit d394d9
    if (result < 0) 
Packit d394d9
      entry = (cache_entry_t *) entry->avl_node.left;
Packit d394d9
    else if (result > 0) 
Packit d394d9
      entry = (cache_entry_t *) entry->avl_node.right;
Packit d394d9
    else /* Word found. */
Packit d394d9
    { 
Packit d394d9
      reference_entry( entry );
Packit d394d9
      current_entry = entry;
Packit d394d9
      current_result = 0;
Packit d394d9
      cache_hits++;
Packit d394d9
      return TRUE;
Packit d394d9
    }
Packit d394d9
  }
Packit d394d9
  return FALSE;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
value_t 
Packit d394d9
next_result_in_cache( void )
Packit d394d9
/* Return the next feature structure for the word found by "word_in_cache".
Packit d394d9
 * Return NULL if no more feature structure exists. */
Packit d394d9
{
Packit d394d9
  value_t result;
Packit d394d9
Packit d394d9
  if (current_result >= current_entry->feat_count) 
Packit d394d9
    return NULL;
Packit d394d9
  result = current_entry->feat_vector[ current_result ];
Packit d394d9
  current_result++;
Packit d394d9
  return result;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
static void 
Packit d394d9
remove_entry_from_cache( void )
Packit d394d9
/* Delete an entry from cache. */
Packit d394d9
{ 
Packit d394d9
  cache_entry_t *entry;
Packit d394d9
  
Packit d394d9
  /* Remove first element from LRU list. */
Packit d394d9
  entry = first_ref;
Packit d394d9
  first_ref = entry->next_ref;
Packit d394d9
  if (first_ref != NULL) 
Packit d394d9
    first_ref->prev_ref = NULL;
Packit d394d9
  else 
Packit d394d9
    last_ref = NULL;
Packit d394d9
Packit d394d9
  /* Remove ENTRY from tree. */
Packit d394d9
  remove_avl_node( (avl_node_t *) entry, (avl_node_t **) &cache_tree, 
Packit d394d9
                   compare_cache_entries );
Packit d394d9
  free_cache_entry( &entry );
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
enter_in_cache( string_t surf_start, string_t surf_end,
Packit d394d9
                int_t feat_count, value_t feat_vector[] )
Packit d394d9
/* Enter the word in [SURF_START..SURF_END] in the cache.
Packit d394d9
 * It has FEAT_COUNT feature structures, stored in FEAT_VECTOR[].
Packit d394d9
 * Be sure that the word is not yet in the cache. */
Packit d394d9
{ 
Packit d394d9
  cache_entry_t *cache_entry;
Packit d394d9
Packit d394d9
  if (entry_count >= max_entry_count) 
Packit d394d9
    remove_entry_from_cache();
Packit d394d9
  cache_entry = new_cache_entry( surf_start, surf_end, 
Packit d394d9
				 feat_count, feat_vector );
Packit d394d9
Packit d394d9
  /* Enter entry in cache tree. */
Packit d394d9
  insert_avl_node( (avl_node_t *) cache_entry, (avl_node_t **) &cache_tree, 
Packit d394d9
                   compare_cache_entries );
Packit d394d9
Packit d394d9
  /* Put entry at end of LRU table. */
Packit d394d9
  if (last_ref != NULL) 
Packit d394d9
    last_ref->next_ref = cache_entry;
Packit d394d9
  cache_entry->prev_ref = last_ref;
Packit d394d9
  cache_entry->next_ref = NULL;
Packit d394d9
  last_ref = cache_entry;
Packit d394d9
  if (first_ref == NULL) 
Packit d394d9
    first_ref = cache_entry;
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
clear_cache( void )
Packit d394d9
/* Remove all entries from the cache. */
Packit d394d9
{ 
Packit d394d9
  while (entry_count > 0) 
Packit d394d9
    remove_entry_from_cache();
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
void 
Packit d394d9
set_cache_size( int_t size )
Packit d394d9
/* Set maximum number of cache entries to SIZE. */
Packit d394d9
{ 
Packit d394d9
  max_entry_count = size;
Packit d394d9
  while (entry_count > max_entry_count) 
Packit d394d9
    remove_entry_from_cache();
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
int_t 
Packit d394d9
get_cache_size( void )
Packit d394d9
/* Get actual number of cache entries. */
Packit d394d9
{ 
Packit d394d9
  return entry_count; 
Packit d394d9
}
Packit d394d9
Packit d394d9
/*---------------------------------------------------------------------------*/
Packit d394d9
Packit d394d9
int_t 
Packit d394d9
get_cache_maximum( void )
Packit d394d9
/* Get maximum number of cache entries. */
Packit d394d9
{ 
Packit d394d9
  return max_entry_count; 
Packit d394d9
}
Packit d394d9
Packit d394d9
/* End of file. =============================================================*/