/*****************************************************************
 * PTlink IRCd is (C) CopyRight PTlink Coders Team 1999-2002     *
 * http://www.ptlink.net/Coders - coders@PTlink.net              *
 * This program is distributed under GNU Public License          *
 * Please read the file COPYING for copyright information.       *
 *****************************************************************
 
  File: rhc.c
  Desc: Recent Hash Cache
  Author: Lamego@PTlink.net
*/
#include <time.h>
#include <string.h>
#include "send.h"
#include "client.h"
#include "rhc.h"
#include "ircd.h"

static struct rhc_entry rhc_list[RHC_SIZE];

/* total values - for stats */
static int t_hits = 0;
static int t_misses = 0;
static int t_collisions = 0;
/*
 * hash_ip()
 * 
 * input        - unsigned long ip address
 * output       - integer value used as index into hash table
 * side effects - hopefully, none
 */
 
static int hash_ip(unsigned long ip)
{
  int hash;
  hash = ((ip >> 12) + ip) & (RHC_SIZE-1);
  return(hash);
}

void clear_rhc(void)
{
  t_hits = 0;
  t_misses = 0;
  t_collisions = 0;
  memset(&rhc_list,0, sizeof(struct rhc_entry) * RHC_SIZE);
}

void set_rhc_status(unsigned long ip, int value)
{
  struct rhc_entry *rhc = &rhc_list[hash_ip(ip)];
  if(rhc->ip && (rhc->ip!=ip))
    t_collisions++;
  rhc->ip = ip;
  rhc->value = value;
  switch(value)
  {
    case
    CACHE_BOT   : rhc->expire = CurrentTime + (60*60*24); break;
    case
    CACHE_ZOMBIE: rhc->expire = CurrentTime + 60; break;
  }
}

int get_rhc_status(unsigned long ip)
{
  struct rhc_entry *rhc = &rhc_list[hash_ip(ip)];
  if(CurrentTime>rhc->expire)
    {
      rhc->ip=0;
      return 0;
    }
  if(rhc->ip==ip)
    {
      ++t_hits;
      return rhc->value;
    }
  ++t_misses;
  return 0;
}

void rhc_stats(struct Client *cptr)
{
  sendto_one(cptr,":%s NOTICE %s :Recent Host Cache Stats",
    me.name, cptr->name);
  if(t_hits+t_misses>0)
    sendto_one(cptr,":%s NOTICE %s :%d hits, %d misses, %d collisions, (%i\%)",
      me.name, cptr->name, t_hits, t_misses, t_collisions, 
      (t_hits/(t_hits+t_misses))*100);
  else
    sendto_one(cptr,":%s NOTICE %s :No stats yet",
      me.name, cptr->name);
  sendto_one(cptr,":%s NOTICE %s :%d bytes of memory used.",
    me.name, cptr->name, sizeof(struct rhc_entry)*RHC_SIZE);
};
