/* clstree.c - Class Tree 에 사용되는 tree 알고리즘
   Copyright (C) 2006 Weongyo Jeong (weongyo@gmail.com)

This file is part of ROVM.

ROVM is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.

ROVM is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  */

#include <stdio.h>

#include "types.h"
#include "mpool.h"
#include "tktree.h"
#include "clstree.h"
#include "sha1.h"
#include "listen.h"
#include "rovm.h"

#include "thread.h"
#include "thread_mutex.h"
#include "thread_cond.h"

#include "mpm_worker_fdqueue.h"
#include "mpm_worker_pod.h"
#include "mpm_worker.h"

#include "connection.h"
#include "request.h"

#include "log.h"
#include "utils.h"
#include "ticket.h"

/*
  (2005-02-05) 현재 clstree 는 Ticket Tree 가 사용하고 있는 SplayTree 를
  그대로 사용중에 있습니다.  Class Tree 를 담을 적당하고 가장 좋은 구조를 
  아직 찾지 못하였기 때문입니다.
*/

/* 이 파일은 Class Tree 을 위한 tree function 들의 wrapper 로 구성되어 있습니다.  
   이렇게 하는 이유는 아직 개발이 테스트 단계이며, 안정적이며 최고의 tree 를 
   아직 선정하지 못하였기 때문입니다.  */

/**
   CLSTREE 에서 하나의 node key 를 제거할 때 호출되는 callback 함수.

   @param k	삭제할 node key
 */
void
rovm_clstree_delete_key (k)
     clstree_key k;
{
  char *tid = (char *) k;

  if (tid)
    rc_free (tid);
}

/**
   CLSTREE 에서 하나의 node value 를 제거할 때 호출되는 callback 함수.

   @param v	삭제할 node value
 */
void
rovm_clstree_delete_value (v)
     clstree_value v;
{
  /* 공사중입니다.  이에 대한 업데이트가 필요합니다.  */
}

/**
   clstree SP 에 key 값과 value 값을 등록한다.

   @note	Wrapper Function 입니다.

   @param sp	생성된 Class Tree
   @param key	등록할 key 값
   @param value 등록한 value 값
   @return	만약 성공적으로 등록이 되었다면 0 을, 그렇지 않다면 -1 을 반환한다.
*/
int
clstree_insert (sp, key, value)
     clstree_t *sp;
     char *key;
     void *value;
{
  splay_tree_node_t n;

  if (!sp || !key)
    return -1;

  n = splay_tree_insert (sp, (splay_tree_key) key, (splay_tree_value) value);
  if (!n)
    return -1;

  return 0;
}

/**
   clstree SP 에서 KEY 값을 가지는 key 와 value 쌍을 *모두* 제거한다.

   @param sp    Class Tree 포인터
   @param key   제거할 Class 경로 (PATH)
 */
void
clstree_remove (sp, key)
     clstree_t *sp;
     char *key;
{
  splay_tree_key backup;
  splay_tree_node_t n = splay_tree_lookup (sp, (clstree_key) key);

  if (!n)
    return;

  backup = n->key;
  /* !참조! splay_tree_remove () 함수에서는 Node 의 Value 값만 제거하지 key 값은
     제거하지 않기 때문에, 이를 아래에서 key 값까지 제거해준다.  */
  splay_tree_remove (sp, (splay_tree_key) n->key);
  rovm_clstree_delete_key (backup);
}

/**
   clstree SP 에서 key 값이 KEY 인 node 를 찾는다.  만약 존재하지 않을 경우,
   NULL 을 반환하며, 발견하였을 경우, 해당 value 값을 반환한다.

   @note	Wrapper Function 입니다.

   @param sp	생성된 Class Tree
   @param key	검색 할 key 값
   @return	발견한 key 값의 value 값을 반환한다.  존재하지 않는 다면, NULL 을
                반환한다.
 */
void *
clstree_lookup (sp, key)
     clstree_t *sp;
     char *key;
{
  splay_tree_node_t n = splay_tree_lookup (sp, (clstree_key) key);

  if (!n)
    return NULL;

  return (void *) n->value;
}

/**
   새로운 Class Tree 를 생성한다.

   @note	Wrapper Function 입니다.

   @param compare_fn		Tree 의 compare function
   @param delete_key_fn		Tree 의 key 를 삭제할 때 사용할 함수.
   @param delete_value_fn	Tree 의 value 를 삭제할 때 사용할 함수.
   @return 새로 생성된 Class Tree 반환한다.
 */
clstree_t *
init_clstree (compare_fn, delete_key_fn, delete_value_fn)
     clstree_compare_fn compare_fn;
     clstree_delete_key_fn delete_key_fn;
     clstree_delete_value_fn delete_value_fn;
{
  return (clstree_t *) splay_tree_new (compare_fn, delete_key_fn, delete_value_fn);
}

/**
   더 이상 Class Tree 가 필요없을 때, 해당 사항들을 모두 제거할 때 사용한다.

   @note	Wrapper Function 입니다.

   @param tk	제거할 clstree_t 구조체.
 */
void
finish_clstree (tk)
     clstree_t *tk;
{
  splay_tree_delete (tk);
}

/**
   Splay Tree 비교 루틴.  K1 과 K2 가 같을 경우, 0 을 반환한다.  그렇지 않을 경우,
   -1 혹은 1 이 반환된다.

   @param k1 Key 1 번
   @param k2 Key 2 번
   @return 만약 K1 과 K2 가 같을 경우 0 을 반환한다.
*/
int
rovm_clstree_compare (k1, k2)
     clstree_key k1;
     clstree_key k2;
{
  return strcmp ((char *) k1, (char *) k2);
}

/**
   ROVM 구조체의 clstree 을 초기화합니다.

   @param r	ROVM 구조체 포인터
   @return	성공적으로 수행되었을 경우 0 을, 그렇지 않다면 -1 을 반환한다.
 */
int
init_rovm_clstree (r)
     struct rovm *r;
{
  ROVM_CLSTREE (r) = init_clstree ((clstree_compare_fn) rovm_clstree_compare,
                                   (clstree_delete_key_fn) rovm_clstree_delete_key,
                                   (clstree_delete_value_fn) rovm_clstree_delete_value);
  if (!ROVM_CLSTREE (r))
    return -1;
  
  return 0;
}

