ftp.nice.ch/pub/next/connectivity/infosystems/WAIStation.1.9.6.N.b.tar.gz#/WAIS/ir/sighash.c

This is sighash.c in view mode; [Download] [Up]

/* WIDE AREA INFORMATION SERVER SOFTWARE:
   No guarantees or restrictions.  See the readme file for the full standard
   disclaimer.

   Brewster@think.com
*/

/* The memory hashtables for building an index. */
/* -brewster 5/90 */

/* main functions:
 *   add_word
 *   finished_add_word
 *   look_up_word
 *
 * The idea is to store up a bunch of words before going to disk.
 * A word entry points to where it will go on disk, and
 * accumulates the entries before doing it.
 *
 * Some of the policy issues in this file are:
 *   How much weight should the first occurance of a word in a document get
 *   over the other occurances.  The first occurance should be worth more
 *   so that words with 3 occurances of "dog" and not "cat"'s should not 
 *   win out over 1 "dog" and 1 "cat" if the question is "Tell me about cats
 *   torture dogs"
 *   The extra weight is 5 at this point.
 *
 */

#ifndef lint
static char *RCSid = "$Header: /proj/wais/wais-8-b5/ir/RCS/sighash.c,v 1.23 92/05/05 13:21:25 shen Exp Locker: shen $";
#endif

/* Change log:
 * $Log:	sighash.c,v $
 * Revision 1.23  92/05/05  13:21:25  shen
 * undo the change make in previous revision 1.22
 * fixed the bug in db->total_word_ccount by checking the last word in t
 * table. If the last word is DICTIONARY_TOTAL_SIZE_WORD, decrement the number
 * of words to add to dictionary file by 1.
 * 
 * Revision 1.22  92/05/05  11:01:54  shen
 * fixed db->total_word_count for incremental update by eliminating adding
 * DICTIONARY_TOTAL_SIZE_WORD to hash table.
 * 
 * Revision 1.21  92/04/29  08:21:15  shen
 * redefine MAX_OCCURANCES to a very big number: 0x10000000.
 * 
 * Revision 1.20  92/03/20  11:04:18  jonathan
 * Added word_postition argument to add word.  See irext.h for explanation.
 * 
 * Revision 1.19  92/03/01  16:11:57  brewster
 * took out analyze_hashtable_distribution
 * 
 * Revision 1.18  92/02/24  19:58:04  jonathan
 * Added code to add the dictionary to the hastable on startup.
 * 
 * Revision 1.17  92/02/12  13:46:18  jonathan
 * Added "$Log" so RCS will put the log message in the header
 * 
*/

/* To Do:
 *  done: Improve the hashing functions.
 *  done: stop inserting into hash table after max number have been accumulated
 *  done: make flush not flush buffers that are too big.
 */
 
#include <ctype.h>
#include <string.h> 	/* for strlen(), memset() */

#include "panic.h"
#include "cutil.h"
#include "futil.h"
#include "irfiles.h"
#include "irhash.h"
#include "stoplist.h"
#include "irinv.h"
#include "sigindex.h"

#ifdef UNIX
#define PRINT_AS_INDEXING true /* also defined in irtfiles.c and irfiles.c */
#else 
#define PRINT_AS_INDEXING false
#endif

#define PROXIMITY /* this turns on writing out of all word occurances */


/* ---------------------------------------------------- */
static hash_entry* look_up_word _AP((char* word,hashtable*
				     the_word_memory_hashtable));
  
static hash_entry* 
look_up_word(word,the_word_memory_hashtable)
char* word;
hashtable* the_word_memory_hashtable;
{
  hash_entry * answer = get_hash(word, the_word_memory_hashtable);
  
  if(NULL != answer)
    return(answer);
  else{
    hash_entry wrd_entry;
    answer = put_hash(word, the_word_memory_hashtable, &wrd_entry);
    answer->number_of_occurances = 0;
    answer->memory_ptr = NULL;
    answer->memory_size = 0;
    answer->current_memory_ptr = answer->memory_ptr;
    answer->current_doc_id = 0;
    return(answer);
  }
}

#ifdef NOTUSED
static unsigned char add_weight _AP((long current_weight,long new_weight));

static unsigned char 
add_weight(current_weight,new_weight)
long current_weight;
long new_weight;
/* add a new weight to the existing one */
{
  /* this should be smarter than this, like doing the log or something */
  if(127 < (current_weight + new_weight)){
    /* the max char.  should be 255, but does not work on all compilers */
    return(127);
  }
  else{
    return(current_weight + new_weight);
  }
}

long write_bytes_to_memory(value,size,ptr)
long value;
long size;
unsigned char* ptr;
{
  /* writes the number into memory lsb first.  
     returns the number of bytes written */
  long i;
  long original_value = value;

  if(size < 0) /* paranoia */
    panic("attempting to write a negative number of bytes");

  ptr += size; /* start at the end of the block and write backwards */
  for (i = 0; i < size; i++){
    ptr--;
    *ptr = (unsigned char)(value & 0xFF);
    value = value >> 8;
  }
  if(value != 0)
    panic("In a call to write_bytes_to_memory, the value %ld can not be represented in %ld bytes", original_value, size);

  return(size);
}
		
#endif /* def NOTUSED */

/* adds a word to the hashtable. 
 * Returns the 0 if successful. See irext.h for more documentation.
 */
long add_word(word, char_pos, line_pos,
	      weight, doc_id, date, word_pair, db, word_position)
     char *word;	/* the word to be indexed, this could be a
			   word pair. If NULL there are no more words
			   to be indexed */
     long char_pos;	/* the position of the start of the
			   word */
     long line_pos;	/* this is passed for the best
			   section calculation */
     long weight;	/* how important the word looks
			   syntactically (such as is it bold)
			   NOT used by signature system */
     long doc_id; 	/* current document, this will never be 0 */
     time_t date; /* display day of this document, 0 if not known */
     long word_pair;
     database* db; /* database to insert the document */
     boolean word_position; /* ignored here. */
{
  /* look up the word in the hashtable */
  /* creates it if necessary */	
  hash_entry* wrd_entry;
  hashtable * the_word_memory_hashtable = db->the_word_memory_hashtable;
  /* printf("Word: '%s' doc_id: %ld, pos: %ld, weight: %ld\n",
     word, doc_id, char_pos, weight); */
  
  if(NULL == db->the_word_memory_hashtable){
    panic("The memory word hashtable is not defined.");
  }

  /* if we have indexed enough words flush the memory copies to disk.
  if(db->number_of_words_in_hashtable == db->flush_after_n_words)
    flush_memory_hashtable_to_disk(db, false);
    ** not done on sig system **
 */
  
  wrd_entry = look_up_word(word, the_word_memory_hashtable);
  wrd_entry->number_of_occurances ++;

  /* check if we have too many of this word before we add it */
#undef MAX_OCCURANCES
#define MAX_OCCURANCES 0x10000000
  if(wrd_entry->number_of_occurances < MAX_OCCURANCES){
    db->number_of_words_in_hashtable ++;
    sig_add_word(word, char_pos, line_pos, weight, doc_id, date, word_pair);
  }
  return(0L);
}

void add_stop_words(the_word_memory_hashtable)
hashtable *the_word_memory_hashtable;
     /* add the stop words to the hashtable.  this must be done before
	adding other words */
{
  init_stop_list();
  while(true){
    char *word = next_stop_word();
    hash_entry* wrd_entry;

    if(NULL == word)
      break;
    wrd_entry = look_up_word(word, the_word_memory_hashtable);
    wrd_entry->number_of_occurances = STOP_WORD_FLAG;
  }
}


long finished_add_word(db)
database *db;
{
  /* write out the dictioanry */
  long i;
  long num_words;

  db->number_of_words = hashtable_count(db->the_word_memory_hashtable);
  init_dict_file_for_writing(db);
  /* analyze_hashtable_distribution(db->the_word_memory_hashtable); */
  sort_hashtable(db->the_word_memory_hashtable);
  /* exclude the last word which is DICTIONARY_TOTAL_SIZE_WORD */
  num_words = hashtable_count(db->the_word_memory_hashtable);
  if ( 0 == strcmp(db->the_word_memory_hashtable->contents[num_words-1].key,
                   DICTIONARY_TOTAL_SIZE_WORD) ) 
    num_words--;
   
  for(i = 0; i < num_words; i++){
    hash_entry * entry = &db->the_word_memory_hashtable->contents[i];
    if(0 == (STOP_WORD_FLAG & entry->number_of_occurances)){
      /* write out the dictionary entry */
      /* printf("Adding word: %s %ld entries\n", entry->word, entry->number_of_occurances); */
      /* the position in this world is a unique id for every word */
      add_word_to_dictionary(entry->key, i,
			     entry->number_of_occurances, db);
    }
  }
  finished_add_word_to_dictionary(db);
  return(sig_finished_add_word(db));
}

/* Add the dictionary to the hastable */

void add_dictionary_to_hashtable(db)
database *db;
{
  /* prints the contents of a dictionary */
  FILE *stream = db->dictionary_stream;
  long i, j, new_number_of_dictionary_blocks;
  extern unsigned char *dictionary_header_block, *dictionary_block;
  extern long number_of_dictionary_blocks;

  if(stream != NULL) {
    waislog(WLOG_LOW, WLOG_INFO, "Adding dictionary to hastable");

    s_fseek(stream, 0L, SEEK_SET);
    new_number_of_dictionary_blocks = read_bytes(DICTIONARY_HEADER_SIZE, stream);
    if(new_number_of_dictionary_blocks > number_of_dictionary_blocks)
      dictionary_header_block = NULL;
    number_of_dictionary_blocks = new_number_of_dictionary_blocks;
    if(NULL == (dictionary_header_block =
		read_dictionary_block(dictionary_header_block,
				      DICTIONARY_HEADER_SIZE,
				      number_of_dictionary_blocks,
				      stream))) {    
      waislog(WLOG_MEDIUM, WLOG_WARNING,
	      "Could not read dictionary header block");
      return;
    }
    for(i = 0; i < number_of_dictionary_blocks; i++){
      long pos = dictionary_block_position(i, dictionary_header_block);
      if(NULL == (dictionary_block =
		  read_dictionary_block(dictionary_block,
					pos, DICTIONARY_BLOCK_SIZE, stream))) {
	waislog(WLOG_MEDIUM, WLOG_WARNING,
		"Could not read dictionary block %ld", pos);
      }
      else
	/* iterate over words */
	for(j = 0; j < DICTIONARY_BLOCK_SIZE; j++) {
	  char *word = dictionary_block_word(j, dictionary_block);
	  hash_entry* wrd_entry;

	  if(word[0] == '\0' )
	    break;
	  wrd_entry = look_up_word(word, db->the_word_memory_hashtable);
	  wrd_entry->number_of_occurances = 
	    dictionary_block_word_occurances(j, dictionary_block);
	}
    }
  }
}

long init_add_word(db, hashtable_size, flush_after_n_words)
     database *db;
     long hashtable_size;
     long flush_after_n_words;
{
  if(NULL != db->the_word_memory_hashtable)
    free_hashtable(db->the_word_memory_hashtable);
  db->the_word_memory_hashtable =
    make_hashtable(0, hashtable_size, sizeof(hash_entry));
  db->flush_after_n_words = 0x7FFFFFFF;  /* a large number */
  sig_init_add_word(db, BATCH_UPDATE, ADD_UPDATE);
  add_dictionary_to_hashtable(db);
  add_stop_words(db->the_word_memory_hashtable);
  return(0);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.