From e7583efae122b25fa35b8ffcb44f4d199f7d81d5 Mon Sep 17 00:00:00 2001
From: Per Cederqvist <ceder@lysator.liu.se>
Date: Tue, 11 Jun 1991 05:42:24 +0000
Subject: [PATCH] Major rewrite. File splitted to simple-cache.c and
 cache-node.c.

---
 src/server/simple-cache.c | 741 +++++++++++++++++++++++++-------------
 1 file changed, 494 insertions(+), 247 deletions(-)

diff --git a/src/server/simple-cache.c b/src/server/simple-cache.c
index f4af4164b..84ce980cf 100644
--- a/src/server/simple-cache.c
+++ b/src/server/simple-cache.c
@@ -9,12 +9,6 @@
  * New save algorithm by ceder.
  */
 
-/*
- * Things to implemet a.s.a.p:
- *
- *  +++ Limit on lru.
- *  +++ Better allocation scheme of Cache-nodes.
- */
 
 /*
  * Possible improvements: +++
@@ -54,42 +48,15 @@
 #include "exp.h"
 
 #include "limits.h"
+#include "cache-node.h"
 
-typedef struct cache_node {
-    struct {
-	u_int	exists : 1;
-	u_int	exists_b : 1;
-	u_int	dirty : 1;		/* [r *ptr modifierad? */
-    } s;
-    void   *snap_shot;		/* Dirty data to be written to file B. */
-				/* (Dirty relative to file A). */
-    void   *ptr;		/* In-core data. */
-    long   pos;			/* Position to element in file A. */
-    long   size;		/* Size on disk. */
-    long   pos_b;		/* Position to element in file B. */
-    long   size_b;		/* Size in file B. */
-    struct cache_node *lru;
-    struct cache_node *mru;
-    int	lock_cnt;
-} Cache_node;
-
-const Cache_node EMPTY_CACHE_NODE =
-    ((Cache_node){{ 0, 0, 0}, NULL, NULL, 0, 0, 0, 0, NULL, NULL, 0});
-
-static Cache_node *pers_mru = NULL;
-static Cache_node *pers_lru = NULL;
-static Cache_node *conf_mru = NULL;
-static Cache_node *conf_lru = NULL;
-static Cache_node *text_mru = NULL;
-static Cache_node *text_lru = NULL;
-
-static Cache_node	* pers_arr[ MAX_CONF ];
-static Cache_node 	* conf_arr[ MAX_CONF ];
 static Small_conf	* small_conf_arr[ MAX_CONF ];
+static Cache_node_mcb	* pers_mcb;
+static Cache_node_mcb 	* conf_mcb;
 static int		  next_free_num = 1;
 
-static Cache_node 	* text_arr[ MAX_TEXT ];
-static int next_text_num = 1;
+static Cache_node_mcb 	* text_mcb;
+static int		  next_text_num = 1;
 
 /* Defined in ramkomd.c */
 extern char datafilename[1024];
@@ -193,77 +160,58 @@ read_text_stat(FILE *fp,
 	return t;
 }
 
-
 static void
-unlink_lru(Cache_node *node,
-	   Cache_node **lru,
-	   Cache_node **mru)
+pers_set_mru(Pers_no pers_no)
 {
-    Cache_node *link;
-    
-    link = node->lru;
-
-    if ( node->lru != NULL )
-	node->lru->mru = node->mru;
-    else if (*lru == node)
-	*lru = node->mru;
-
-    if ( node->mru != NULL )
-	node->mru->lru = link;
-    else if (*mru == node)
-	*mru = link;
+    set_mru(pers_mcb, pers_no);
 }
 
 static void
-insert_mru(Cache_node *node,
-	   Cache_node **lru,
-	   Cache_node **mru)
+text_set_mru(Text_no text_no)
 {
-    node->mru = NULL;
-    node->lru = *mru;
-    *mru = node;
-    if ( *lru == NULL )
-	*lru = node;
-
-    if ( node->lru != NULL )
-	node->lru->mru = node;
+    set_mru(text_mcb, text_no);
 }
 
 static void
-pers_set_mru(Pers_no pers_no)
+conf_set_mru(Conf_no conf_no)
 {
-    Cache_node *node = pers_arr[ pers_no ];
-
-    if (node == NULL)
-	restart_kom("pers_set_mru(%d): nonexistent.\n", pers_no);
+    set_mru(conf_mcb, conf_no);
+}
 
-    unlink_lru(node, &pers_lru, &pers_mru);
-    insert_mru(node, &pers_lru, &pers_mru);
+static Cache_node *
+get_pers_node(Pers_no pers_no)
+{
+    return get_cache_node(pers_mcb, pers_no);
 }
 
 static void
-text_set_mru(Text_no text_no)
+unlink_text_lru (Cache_node *node)
 {
-    Cache_node *node = text_arr[ text_no ];
-
-    if ( node == NULL )
-	restart_kom("text_set_mru(%d): nonexistent.\n", text_no);
-
-    unlink_lru(node, &text_lru, &text_mru);
-    insert_mru(node, &text_lru, &text_mru);
+    unlink_lru (node, &text_mcb->lru, &text_mcb->mru);
 }
 
+static void
+unlink_conf_lru (Cache_node *node)
+{
+    unlink_lru (node, &conf_mcb->lru, &conf_mcb->mru);
+}
 
 static void
-conf_set_mru(Conf_no conf_no)
+unlink_pers_lru (Cache_node *node)
 {
-    Cache_node *node = conf_arr[ conf_no ];
+    unlink_lru (node, &pers_mcb->lru, &pers_mcb->mru);
+}
 
-    if ( node == NULL )
-	restart_kom("conf_set_mru(%d): nonexistent.\n", conf_no);
+static Cache_node *
+get_conf_node(Conf_no conf_no)
+{
+    return get_cache_node(conf_mcb, conf_no);
+}
 
-    unlink_lru(node, &conf_lru, &conf_mru);
-    insert_mru(node, &conf_lru, &conf_mru);
+static Cache_node *
+get_text_node(Text_no text_no)
+{
+    return get_cache_node(text_mcb, text_no);
 }
 
 	
@@ -307,7 +255,11 @@ cached_get_conf_type (Conf_no conf_no)
     if ( conf_no < 1 || conf_no >= next_free_num )
 	restart_kom("cached_get_conf_type(%d): next_free_num==%d",
 		    conf_no, next_free_num);
-    
+
+    if ( small_conf_arr [ conf_no ] == NULL )
+	restart_kom("cached_get_conf_type(%d): conference does not exist.\n",
+		    conf_no);
+
     return small_conf_arr [ conf_no ]->type;
 }
 
@@ -320,11 +272,15 @@ cached_get_conf_type (Conf_no conf_no)
 void
 mark_person_as_changed(Pers_no	pers_no)
 {
+    Cache_node *node;
+
+    node = get_pers_node(pers_no);
+    
     TRACE2("Person %d is changed\n", pers_no);
-    if ( pers_arr[ pers_no ] == NULL || pers_arr[ pers_no ]->s.exists == 0)
+    if ( node == NULL || node->s.exists == 0)
 	restart_kom("mark_person_as_changed(%d): nonexistent.\n", pers_no);
 
-    pers_arr[ pers_no ]->s.dirty = 1;
+    node->s.dirty = 1;
     pers_set_mru( pers_no );
 }
 
@@ -332,41 +288,40 @@ mark_person_as_changed(Pers_no	pers_no)
 void
 mark_conference_as_changed(Conf_no	conf_no)
 {
+    Cache_node *node;
+
+    node = get_conf_node (conf_no);
+
     TRACE2("Conf.  %d is changed\n", conf_no);
-    if ( conf_arr[ conf_no ] == NULL || conf_arr[ conf_no ]->s.exists == 0)
+    if ( node == NULL || node->s.exists == 0)
 	restart_kom("mark_conference_as_changed(%d): nonexistent.\n", conf_no);
 
-    conf_arr[ conf_no ]->s.dirty = 1;
+    node->s.dirty = 1;
     conf_set_mru( conf_no );
     small_conf_arr[ conf_no ]->highest_local_no
-	= (((Conference *)conf_arr [ conf_no ]->ptr)->texts.first_local_no - 1
-	   + ((Conference *)conf_arr [ conf_no ]->ptr)->texts.no_of_texts );
+	= (((Conference *)node->ptr)->texts.first_local_no - 1
+	   + ((Conference *)node->ptr)->texts.no_of_texts );
 }
 
 void
 mark_text_as_changed( Text_no text_no )
 {
+    Cache_node *node;
+
+    node = get_text_node (text_no);
+
     TRACE2("Text %d is changed.\n", text_no);
     if ( text_no < 1 || text_no >= next_text_num
-	|| text_arr[ text_no ] == NULL || text_arr[ text_no ]->s.exists == 0)
+	|| node == NULL || node->s.exists == 0)
     {
 	restart_kom("mark_text_as_changed(%d): nonexistent.\n", text_no);
     }
 
-    text_arr[ text_no ]->s.dirty = 1;
-    text_set_mru( text_no );
+    node->s.dirty = 1;
+    text_set_mru (text_no);
 }    
 
 
-static Cache_node *
-alloc_cache_node(void)
-{
-    Cache_node *c;
-
-    c = smalloc(sizeof(Cache_node));
-    *c = EMPTY_CACHE_NODE;
-    return c;
-}
 
 /*
  * Person-related calls
@@ -376,6 +331,8 @@ alloc_cache_node(void)
 extern Success
 cached_create_person( Pers_no person )
 {
+    Cache_node *node;
+
     TRACE2("Person %d is being created.\n", person);
 
     if ( person < 1 || person >= next_free_num )
@@ -384,16 +341,21 @@ cached_create_person( Pers_no person )
 		    person, next_free_num);
     }
 
-    if ( pers_arr[ person ] != NULL )
+    if ( get_pers_node(person) != NULL )
     {
 	restart_kom("cached_create_person(%d): Person existed.\n",
 		    person);
     }
 
-    pers_arr[ person ] = alloc_cache_node();
-    pers_arr[ person ]->ptr = alloc_person();
-    pers_arr[ person ]->s.dirty = 1;
-    pers_arr[ person ]->s.exists = 1;
+    create_cache_node (pers_mcb, person);
+    node = get_pers_node (person);
+
+    if ( node == NULL )
+	restart_kom("cached_create_person(): couldn't get cache_node.\n");
+    
+    node->ptr = alloc_person();
+    node->s.dirty = 1;
+    node->s.exists = 1;
     pers_set_mru( person );
     return OK;
 }
@@ -402,6 +364,8 @@ cached_create_person( Pers_no person )
 extern Person *
 cached_get_person_stat( Pers_no	person )
 {
+    Cache_node *node;
+
     TRACE2("cached_get_person_stat %d\n", person);
 
     if ( person == 0 )
@@ -409,33 +373,33 @@ cached_get_person_stat( Pers_no	person )
 	kom_errno = KOM_CONF_ZERO;
 	return NULL;
     }
-    
-    if ( person >= next_free_num || pers_arr[ person ] == NULL
-	|| pers_arr[ person ]->s.exists == 0 )
+
+    node = get_pers_node (person);
+
+    if ( person >= next_free_num || node == NULL
+	|| node->s.exists == 0 )
     {
 	kom_errno = KOM_UNDEF_PERS;
 	return NULL;
     }
 
-    if ( pers_arr[ person ]->ptr != NULL )
+    if ( node->ptr != NULL )
     {
 	pers_set_mru( person );
-	return pers_arr[ person ]->ptr;
+	return node->ptr;
     }
 
-    if ( pers_arr[ person ]->snap_shot != NULL )
+    if ( node->snap_shot != NULL )
     {
-	pers_arr[ person ]->ptr = copy_person(pers_arr[ person ]->snap_shot);
+	node->ptr = copy_person (node->snap_shot);
 	pers_set_mru (person);
-	return pers_arr[ person ]->ptr;
+	return node->ptr;
     }
 
-    pers_arr[ person ]->ptr = read_person(file_a,
-					  pers_arr[ person ]->pos,
-					  pers_arr[ person ]->size);
+    node->ptr = read_person(file_a, node->pos, node->size);
 
     pers_set_mru (person);
-    return pers_arr[ person ]->ptr;
+    return node->ptr;
 }
 
 
@@ -447,6 +411,7 @@ cached_create_conf (String  name)
 {
     Conference * conf_c;
     Conf_no	 conf_no;
+    Cache_node  *node;
 
     TRACE1("cached_create_conf( ");
     TRACESTR(name);
@@ -460,20 +425,25 @@ cached_create_conf (String  name)
     
     conf_no = next_free_num++;
 
-    conf_arr[ conf_no ] = alloc_cache_node();
-    conf_arr[ conf_no ]->s.exists = 1;
-    conf_arr[ conf_no ]->s.dirty = 1;
-    conf_arr[ conf_no ]->ptr = conf_c = alloc_conference();
+    create_cache_node (conf_mcb, conf_no);
+    node = get_conf_node (conf_no);
+
+    if ( node == NULL )
+	restart_kom("cached_create_conf(): failed to allocate cache_node.\n");
+    
+    node->s.exists = 1;
+    node->s.dirty = 1;
+    node->ptr = conf_c = alloc_conference();
     conf_set_mru(conf_no);    
 
-    pers_arr[ conf_no ] = NULL;
+    zero_init_cache_node (pers_mcb, conf_no);
     small_conf_arr[ conf_no ] = alloc_small_conf();
 
     conf_c->name = EMPTY_STRING;
     s_strcpy(&conf_c->name, name);
     cached_change_name( conf_no, name);
 
-    TRACE2(" number %d\n", conf_no);
+    TRACE2("Created conference number %d\n", conf_no);
     
     return conf_no;
 }
@@ -482,26 +452,29 @@ cached_create_conf (String  name)
 extern Success
 cached_delete_conf( Conf_no	conf )
 {
+    Cache_node *node;
+
     if ( conf == 0 )
     {
 	kom_errno = KOM_CONF_ZERO;
 	return FAILURE;
     }
-    
-    if ( conf >= next_free_num || conf_arr[ conf ] == NULL
-	|| conf_arr[ conf ]->s.exists == 0 )
+
+    node = get_conf_node (conf);
+
+    if ( conf >= next_free_num || node == NULL || node->s.exists == 0 )
     {
 	kom_errno = KOM_UNDEF_CONF;
 	return FAILURE;
     }
 
-    if ( conf_arr[ conf ]->lock_cnt > 0 )
-	log("cached_delete_conf(%d): lock_cnt === %d\n",
-	    conf, conf_arr[ conf ]->lock_cnt);
+    if ( node->lock_cnt > 0 )
+	log("WNG: cached_delete_conf(%d): lock_cnt === %d\n",
+	    conf, node->lock_cnt);
 
-    free_conference(conf_arr[ conf ]->ptr);
-    conf_arr[ conf ]->ptr = NULL;
-    conf_arr[ conf ]->s.exists = 0;
+    free_conference(node->ptr);
+    node->ptr = NULL;
+    node->s.exists = 0;
 
     return OK;
 }
@@ -509,14 +482,17 @@ cached_delete_conf( Conf_no	conf )
 Success
 cached_delete_person(Pers_no pers)
 {
+    Cache_node *node;
+
     if ( pers == 0 )
     {
 	kom_errno = KOM_CONF_ZERO;
 	return FAILURE;
     }
-    
-    if ( pers >= next_free_num || pers_arr[ pers ] == NULL
-	|| pers_arr[ pers ]->s.exists == 0 )
+
+    node = get_pers_node (pers);
+
+    if ( pers >= next_free_num || node == NULL || node->s.exists == 0 )
     {
 	log("cached_delete_person(): attempt to"
 	    " delete non-existing person.\n");
@@ -524,27 +500,31 @@ cached_delete_person(Pers_no pers)
 	return FAILURE;
     }
 
-    if ( pers_arr[ pers ]->lock_cnt > 0 )
+    if ( node->lock_cnt > 0 )
 	log("cached_delete_pers(%d): lock_cnt === %d\n",
-	    pers, pers_arr[ pers ]->lock_cnt);
+	    pers, node->lock_cnt);
 
-    free_person(pers_arr[ pers ]->ptr);
-    pers_arr[ pers ]->ptr = NULL;
-    pers_arr[ pers ]->s.exists = 0;
+    free_person (node->ptr);
+    node->ptr = NULL;
+    node->s.exists = 0;
     return OK;
 }
 
 Success
 cached_delete_text(Text_no text)
 {
+    Cache_node *node;
+
     if ( text == 0 )
     {
 	kom_errno = KOM_TEXT_ZERO;
 	return FAILURE;
     }
-    
-    if ( text >= next_text_num || text_arr[ text ] == NULL
-	|| text_arr[ text ]->s.exists == 0 )
+
+    node = get_text_node (text);
+
+    if ( text >= next_text_num || node == NULL
+	|| node->s.exists == 0 )
     {
 	log("cached_delete_text(): attempt to"
 	    " delete non-existing text %d.\n", text);
@@ -552,22 +532,24 @@ cached_delete_text(Text_no text)
 	return FAILURE;
     }
 
-    if ( text_arr[ text ]->lock_cnt > 0 )
+    if ( node->lock_cnt > 0 )
 	log("cached_delete_text(%d): lock_cnt === %d\n",
-	    text, text_arr[ text ]->lock_cnt);
+	    text, node->lock_cnt);
 
 
-    free_text_stat(text_arr[ text ]->ptr);
-    text_arr[ text ]->ptr = NULL;
-    text_arr[ text ]->s.exists = 0;
+    free_text_stat(node->ptr);
+    node->ptr = NULL;
+    node->s.exists = 0;
 
     return OK;
 }
 
 
 extern Conference *
-cached_get_conf_stat(	Conf_no		conf_no )
+cached_get_conf_stat (Conf_no   conf_no)
 {
+    Cache_node *node;
+
     TRACE2("cached_get_conf_stat %d\n", conf_no);
 
     if ( conf_no == 0 )
@@ -575,33 +557,32 @@ cached_get_conf_stat(	Conf_no		conf_no )
 	kom_errno = KOM_CONF_ZERO;
 	return NULL;
     }
-    
-    if ( conf_no >= next_free_num || conf_arr[ conf_no ] == NULL
-	|| conf_arr[ conf_no ]->s.exists == 0 )
+
+    node = get_conf_node (conf_no);
+
+    if ( conf_no >= next_free_num || node == NULL || node->s.exists == 0 )
     {
 	kom_errno = KOM_UNDEF_CONF;
 	return NULL;
     }
 
-    if ( conf_arr[ conf_no ]->ptr != NULL )
+    if ( node->ptr != NULL )
     {
-	conf_set_mru( conf_no );
-	return conf_arr[ conf_no ]->ptr;
+	conf_set_mru (conf_no);
+	return node->ptr;
     }
 
-    if ( conf_arr[ conf_no ]->snap_shot != NULL )
+    if ( node->snap_shot != NULL )
     {
-	conf_arr[ conf_no ]->ptr = copy_conf(conf_arr[ conf_no ]->snap_shot);
+	node->ptr = copy_conf (node->snap_shot);
 	conf_set_mru (conf_no);
-	return conf_arr[ conf_no ]->ptr;
+	return node->ptr;
     }
 
-    conf_arr[ conf_no ]->ptr
-	= read_conference(file_a, conf_arr[ conf_no ]->pos, 
-			  conf_arr[ conf_no ]->size);
+    node->ptr = read_conference(file_a, node->pos, node->size);
 
     conf_set_mru (conf_no);
-    return conf_arr[ conf_no ]->ptr;
+    return node->ptr;
 }
 
 /*
@@ -610,8 +591,14 @@ cached_get_conf_stat(	Conf_no		conf_no )
 Bool
 cached_conf_exists(Conf_no conf_no)
 {
-    return (conf_no > 0 && conf_no < next_free_num
-	    && conf_arr[ conf_no ]->s.exists != 0) ? TRUE : FALSE;
+    Cache_node *node;
+
+    if (conf_no == 0 || conf_no >= next_free_num )
+	return FALSE;
+
+    node = get_conf_node (conf_no);
+
+    return node != NULL && node->s.exists != 0;
 }
 
     
@@ -655,6 +642,8 @@ cached_get_text( Text_no text )
 extern Text_stat *	/* NULL on error */
 cached_get_text_stat(	Text_no		text )
 {
+    Cache_node *node;
+
     TRACE2("cached_get_text_stat(%d);  next_text_num == ", text);
     TRACE2("%d\n", next_text_num);
 
@@ -663,37 +652,36 @@ cached_get_text_stat(	Text_no		text )
 	kom_errno = KOM_TEXT_ZERO;
 	return NULL;
     }
-    
-    if ( text >= next_text_num || text_arr[ text ] == NULL
-	|| text_arr[ text ]->s.exists == 0 )
+
+    node = get_text_node (text);
+
+    if ( text >= next_text_num || node == NULL || node->s.exists == 0 )
     {
 	TRACE1("cached_get_text_stat: no such text.\n");
 	kom_errno = KOM_NO_SUCH_TEXT;
 	return NULL;
     }
 
-    if ( text_arr[ text ]->ptr != NULL )
+    if ( node->ptr != NULL )
     {
 	TRACE1("Found in ptr.\n");
 	text_set_mru( text );
-	return text_arr[ text ]->ptr;
+	return node->ptr;
     }
 
-    if ( text_arr[ text ]->snap_shot != NULL )
+    if ( node->snap_shot != NULL )
     {
 	TRACE1("Found in snap_shot\n");
-	text_arr[ text ]->ptr = copy_text_stat(text_arr[ text ]->snap_shot);
+	node->ptr = copy_text_stat(node->snap_shot);
 	text_set_mru (text);
-	return text_arr[ text ]->ptr;
+	return node->ptr;
     }
 
     TRACE1("Found in file A.\n");
-    text_arr[ text ]->ptr
-	= read_text_stat(file_a, text_arr[ text ]->pos,
-			 text_arr[ text ]->size);
+    node->ptr = read_text_stat(file_a, node->pos, node->size);
 
     text_set_mru (text);
-    return text_arr[ text ]->ptr;
+    return node->ptr;
 }
 
 
@@ -707,6 +695,7 @@ extern Text_no
 cached_create_text( String message)
 {
     Text_no tno;
+    Cache_node *node;
 
     tno = next_text_num++;
 
@@ -720,18 +709,22 @@ cached_create_text( String message)
 	return 0;
     }
 
-    text_arr[ tno ] = alloc_cache_node();
+    create_cache_node(text_mcb, tno);
+    node = get_text_node (tno);
 
-    text_arr[ tno ]->s.exists = 1;
-    text_arr[ tno ]->s.dirty = 1;
-    text_arr[ tno ]->ptr = alloc_text_stat();
-    ((Text_stat *)text_arr[ tno ]->ptr)->no_of_misc = 0;
-    ((Text_stat *)text_arr[ tno ]->ptr)->misc_items = NULL;
-    ((Text_stat *)text_arr[ tno ]->ptr)->no_of_marks = 0;
-    ((Text_stat *)text_arr[ tno ]->ptr)->no_of_lines = 0;
-    ((Text_stat *)text_arr[ tno ]->ptr)->no_of_chars = 0;
+    if ( node == NULL )
+	restart_kom("cached_create_text(): could'nt create cache-node.\n");
+    
+    node->s.exists = 1;
+    node->s.dirty = 1;
+    node->ptr = alloc_text_stat();
+    ((Text_stat *)node->ptr)->no_of_misc = 0;
+    ((Text_stat *)node->ptr)->misc_items = NULL;
+    ((Text_stat *)node->ptr)->no_of_marks = 0;
+    ((Text_stat *)node->ptr)->no_of_lines = 0;
+    ((Text_stat *)node->ptr)->no_of_chars = 0;
     fseek(text_file, 0, SEEK_END);
-    ((Text_stat *)text_arr[ tno ]->ptr)->file_pos = ftell(text_file);
+    ((Text_stat *)node->ptr)->file_pos = ftell(text_file);
 
     text_set_mru( tno );
 
@@ -752,12 +745,16 @@ cached_create_text( String message)
 Text_no
 traverse_text(Text_no seed)
 {
+    Cache_node *node;
+
     seed++;
     
-    while ( seed < next_text_num
-	   && (text_arr[ seed ] == NULL
-	       || text_arr[ seed ]->s.exists == 0 ) )
+    while ( seed < next_text_num )
     {
+	node = get_text_node (seed);
+	if ( node != NULL && node->s.exists != 0 )
+	    break;
+
 	seed++;
     }
     
@@ -767,12 +764,16 @@ traverse_text(Text_no seed)
 Pers_no
 traverse_person(Pers_no seed)
 {
+    Cache_node *node;
+
     seed++;
 
-    while ( seed < next_free_num
-	   && (pers_arr[ seed ] == NULL
-	       | pers_arr[ seed ]->s.exists == 0 ))
+    while ( seed < next_free_num )
     {
+	node = get_pers_node (seed);
+	if (node != NULL && node->s.exists != 0 )
+	    break;
+
 	seed++;
     }
 
@@ -782,12 +783,16 @@ traverse_person(Pers_no seed)
 Conf_no
 traverse_conference(Conf_no seed)
 {
+    Cache_node *node;
+
     seed++;
     
-    while ( seed < next_free_num
-	   && (conf_arr[ seed ] == NULL
-	       || conf_arr[ seed ]->s.exists == 0 ))
+    while ( seed < next_free_num )
     {
+	node = get_conf_node (seed);
+	if (node != NULL && node->s.exists != 0 )
+	    break;
+
 	seed++;
     }
 
@@ -811,41 +816,52 @@ cached_get_highest_local_no (Conf_no conf_no)
 void
 cached_lock_person(Pers_no pers_no)
 {
-    if ( pers_arr[ pers_no ]->s.exists == 0 )
+    Cache_node *node;
+
+    node = get_pers_node(pers_no);
+    
+    if ( node == NULL || node->s.exists == 0 )
 	restart_kom("cached_lock_person(%d): nonexistent.\n", pers_no);
 
-    if ( pers_arr[ pers_no ]->ptr == NULL )
+    if ( node->ptr == NULL )
     {
-	Person *ptr;
+	Person *pers_stat_ptr;
 
-	ptr = cached_get_person_stat( pers_no );
+	pers_stat_ptr = cached_get_person_stat( pers_no );
 
-	if ( ptr == NULL )
+	if ( pers_stat_ptr == NULL )
 	    restart_kom("cached_lock_person(%d): couldn't read in person.\n",
 			pers_no);
 
-	if ( ptr != pers_arr[ pers_no ]->ptr )
-	    restart_kom("cached_lock_person(%d): ptr == %d, pers_arr[pers_no]"
-			"->ptr == %d.\n", pers_no, ptr,
-			pers_arr[ pers_no ]->ptr);
+	if ( pers_stat_ptr != node->ptr )
+	    restart_kom("cached_lock_person(%d): pers_stat_ptr == %d, node"
+			"->ptr == %d.\n", pers_no, pers_stat_ptr,
+			node->ptr);
     }
 
-    pers_arr[ pers_no ]->lock_cnt++;
+    node->lock_cnt++;
 }
 
 /* Decrease reference count. If zero, unlock person. */
 void
 cached_unlock_person(Pers_no pers_no)
 {
-    if ( pers_arr[ pers_no ]->lock_cnt <= 0 )
+    Cache_node *node;
+
+    node = get_pers_node (pers_no);
+
+    if ( node == NULL )
+	restart_kom("cached_unlock_person(): couldn't get cache-node.\n");
+
+    if ( node->lock_cnt <= 0 )
     {
 	log("cached_unlock_person(%d): lock_cnt == %d.\n",
-	    pers_no, pers_arr[ pers_no ]->lock_cnt);
+	    pers_no, node->lock_cnt);
 
-	pers_arr[ pers_no ]->lock_cnt = 0;
+	node->lock_cnt = 0;
     }
     else
-	pers_arr[ pers_no ]->lock_cnt--;
+	node->lock_cnt--;
 }
 
 
@@ -853,41 +869,54 @@ cached_unlock_person(Pers_no pers_no)
 void
 cached_lock_conf(Conf_no conf_no)
 {
-    if ( conf_arr[ conf_no ]->s.exists == 0 )
+    Cache_node *node;
+
+    node = get_conf_node(conf_no);
+
+    if ( node == NULL)
+	restart_kom("cached_lock_conf(): can't get cache-node.\n");
+
+    if ( node->s.exists == 0 )
 	restart_kom("cached_lock_conf(%d): nonexistent.\n", conf_no);
 
-    if ( conf_arr[ conf_no ]->ptr == NULL )
+    if ( node->ptr == NULL )
     {
-	Conference *ptr;
+	Conference *conference_ptr;
 
-	ptr = cached_get_conf_stat( conf_no );
+	conference_ptr = cached_get_conf_stat( conf_no );
 
-	if ( ptr == NULL )
+	if ( conference_ptr == NULL )
 	    restart_kom("cached_lock_conf(%d): couldn't read in conf.\n",
 			conf_no);
 
-	if ( ptr != conf_arr[ conf_no ]->ptr )
-	    restart_kom("cached_lock_conf(%d): ptr == %d, conf_arr[conf_no]"
-			"->ptr == %d.\n", conf_no, ptr,
-			conf_arr[ conf_no ]->ptr);
+	if ( conference_ptr != node->ptr )
+	    restart_kom("cached_lock_conf(%d): conference_ptr == %d, node"
+			"->ptr == %d.\n", conf_no, conference_ptr,
+			node->ptr);
     }
 
-    conf_arr[ conf_no ]->lock_cnt++;
+    node->lock_cnt++;
 }
 
 /* Decrease reference count. If zero, unlock conf. */
 void
 cached_unlock_conf(Conf_no conf_no)
 {
-    if ( conf_arr[ conf_no ]->lock_cnt <= 0 )
+    Cache_node *node;
+
+    node = get_conf_node(conf_no);
+    if ( node == NULL )
+	restart_kom("cached_unlock_conf(): can't get node.\n");
+
+    if ( node->lock_cnt <= 0 )
     {
 	log("cached_unlock_conf(%d): lock_cnt == %d.\n",
-	    conf_no, conf_arr[ conf_no ]->lock_cnt);
+	    conf_no, node->lock_cnt);
 
-	conf_arr[ conf_no ]->lock_cnt = 0;
+	node->lock_cnt = 0;
     }
     else
-	conf_arr[ conf_no ]->lock_cnt--;
+	node->lock_cnt--;
 }
 
 
@@ -1041,7 +1070,7 @@ pre_sync(void)
 
     for ( i = 1; i < highest_conf_no; i++ )
     {
-	node = conf_arr[i];
+	node = get_conf_node(i);
 
 	if ( node != NULL )
 	{
@@ -1053,7 +1082,7 @@ pre_sync(void)
 
 		if ( node->lock_cnt == 0 )
 		{
-		    unlink_lru(node, &conf_lru, &conf_mru);
+		    unlink_conf_lru(node);
 		    node->snap_shot = node->ptr;
 		    node->ptr = NULL;
 		}
@@ -1069,7 +1098,7 @@ pre_sync(void)
 
     for ( i = 1; i < highest_conf_no; i++ )
     {
-	node = pers_arr[i];
+	node = get_pers_node(i);
 
 	if ( node != NULL )
 	{
@@ -1081,7 +1110,7 @@ pre_sync(void)
 
 		if ( node->lock_cnt == 0 )
 		{
-		    unlink_lru(node, &pers_lru, &pers_mru);
+		    unlink_pers_lru(node);
 		    node->snap_shot = node->ptr;
 		    node->ptr = NULL;
 		}
@@ -1098,7 +1127,7 @@ pre_sync(void)
 
     for ( i = 1; i < highest_text_no; i++ )
     {
-	node = text_arr[i];
+	node = get_text_node(i);
 
 	if ( node != NULL )
 	{
@@ -1110,7 +1139,7 @@ pre_sync(void)
 
 		if ( node->lock_cnt == 0 )
 		{
-		    unlink_lru(node, &text_lru, &text_mru);
+		    unlink_text_lru(node);
 		    node->snap_shot = node->ptr;
 		    node->ptr = NULL;
 		}
@@ -1170,6 +1199,7 @@ copy_file(FILE *from,
     {
 	sync_state = sync_error;
 	log("sync: copy_file(): fseek failed.\n");
+	sfree(buf);
 	return;
     }
     
@@ -1180,6 +1210,7 @@ copy_file(FILE *from,
 	    from_pos, len, result);
 
 	sync_state = sync_error;
+	sfree(buf);
 	return;
     }
 
@@ -1187,6 +1218,7 @@ copy_file(FILE *from,
     {
 	sync_state = sync_error;
 	log("sync: copy_file(): second fseek failed.\n");
+	sfree(buf);
 	return;
     }
 
@@ -1194,6 +1226,7 @@ copy_file(FILE *from,
     {
 	sync_state = sync_error;
 	log("sync: copy_file(): fwrite failed.\n");
+	sfree(buf);
 	return;
     }
 
@@ -1207,7 +1240,7 @@ save_one_conf(void)
     
     if (sync_next < highest_conf_no)
     {
-	cn = conf_arr[ sync_next ];
+	cn = get_conf_node (sync_next);
 
 	if ( cn == NULL )
 	{
@@ -1263,7 +1296,7 @@ save_one_pers(void)
     
     if (sync_next < highest_conf_no)
     {
-	cn = pers_arr[ sync_next ];
+	cn = get_pers_node (sync_next);
 
 	if ( cn == NULL )
 	{
@@ -1325,37 +1358,40 @@ post_sync(void)
 
     for ( i = 1; i < highest_conf_no; i++ )
     {
-	node = conf_arr[i];
+	node = get_conf_node(i);
 	if ( node != NULL )
 	{
 	    node->pos = node->pos_b;
 	    node->size = node->size_b;
 	    free_conference(node->snap_shot);
 	    node->snap_shot = NULL;
+	    /* +++ Delete if it no longer exists. */
 	}
     }
 
     for ( i = 1; i < highest_conf_no; i++ )
     {
-	node = pers_arr[i];
+	node = get_pers_node(i);
 	if ( node != NULL )
 	{
 	    node->pos = node->pos_b;
 	    node->size = node->size_b;
 	    free_person(node->snap_shot);
 	    node->snap_shot = NULL;
+	    /* +++ Delete if it no longer exists. */
 	}
     }
 
     for ( i = 1; i < highest_text_no; i++ )
     {
-	node = text_arr[i];
+	node = get_text_node(i);
 	if ( node != NULL )
 	{
 	    node->pos = node->pos_b;
 	    node->size = node->size_b;
 	    free_text_stat(node->snap_shot);
 	    node->snap_shot = NULL;
+	    /* +++ Delete if it no longer exists. */
 	}
     }
 }
@@ -1369,7 +1405,7 @@ save_one_text(void)
     
     if (sync_next < highest_text_no)
     {
-	cn = text_arr[ sync_next ];
+	cn = get_text_node(sync_next);
 
 	if ( cn == NULL )
 	{
@@ -1550,6 +1586,12 @@ init_cache(void)
     Person tmp_pers = EMPTY_PERSON;
     Text_stat tmp_text = EMPTY_TEXT_STAT;
 
+    pers_mcb = create_cache_node_mcb(100, MAX_CONF);
+    conf_mcb = create_cache_node_mcb(100, MAX_CONF);
+    text_mcb = create_cache_node_mcb(100, MAX_TEXT);
+
+
+
     if ( (text_file = fopen(textfilename, "a+b")) == NULL )
     {
 	restart_kom("ERROR: init_cache: can't open text file.\n");
@@ -1589,11 +1631,12 @@ init_cache(void)
 	switch(getc(file_a))
 	{
 	case '@':
-	    conf_arr[ i ] = NULL;
+	    zero_init_cache_node(conf_mcb, i);
 	    break;
 
 	case '+':
-	    node = conf_arr[ i ] = alloc_cache_node();
+	    create_cache_node(conf_mcb, i);
+	    node = get_conf_node(i);
 	    node->s.exists = 1;
 
 	    node->pos = ftell(file_a) - 1; /* Don't forget the '+' */
@@ -1618,11 +1661,12 @@ init_cache(void)
 	switch(getc(file_a))
 	{
 	case '@':
-	    pers_arr[ i ] = NULL;
+	    zero_init_cache_node(pers_mcb, i);
 	    break;
 
 	case '+':
-	    node = pers_arr[ i ] = alloc_cache_node();
+	    create_cache_node(pers_mcb, i);
+	    node = get_pers_node(i); 
 	    node->s.exists = 1;
 	    node->pos = ftell(file_a) - 1; /* Don't forget the '+' */
 	    if ( fparse_person(file_a, &tmp_pers) != OK )
@@ -1643,11 +1687,12 @@ init_cache(void)
 	switch(getc(file_a))
 	{
 	case '@':
-	    text_arr[ i ] = NULL;
+	    zero_init_cache_node(text_mcb, i);
 	    break;
 
 	case '+':
-	    node = text_arr[ i ] = alloc_cache_node();
+	    create_cache_node(text_mcb, i);
+	    node = get_text_node(i);
 	    node->s.exists = 1;
 
 	    node->pos = ftell(file_a) - 1; /* Don't forget the '+' */
@@ -1682,3 +1727,205 @@ cache_sync_all(void)
     while ( sync_part() != TRUE )
 	;
 }
+
+void
+free_all_cache (void)
+{
+    int i;
+    Cache_node *node;
+
+    for ( i = 0; i < next_free_num; i++ )
+    {
+	node = get_conf_node(i);
+	if ( node != NULL )
+	{
+	    if ( node->snap_shot != NULL )
+	    {
+		free_conference (node->snap_shot);
+		node->snap_shot = NULL;
+	    }
+
+	    if ( node->ptr != NULL )
+	    {
+		free_conference (node->ptr);
+		node->ptr = NULL;
+	    }
+	}
+
+	destruct_cache_node (conf_mcb, i);
+
+	node = get_pers_node(i);
+	if ( node != NULL )
+	{
+	    if ( node->snap_shot != NULL )
+	    {
+		free_person (node->snap_shot);
+		node->snap_shot = NULL;
+	    }
+
+	    if ( node->ptr != NULL )
+	    {
+		free_person (node->ptr);
+		node->ptr = NULL;
+	    }
+	}
+
+	destruct_cache_node (pers_mcb, i);
+
+	s_clear ( &small_conf_arr[i]->name );
+    }
+
+    for ( i = 0; i < next_text_num; i++ )
+    {
+	node = get_text_node(i);
+	if ( node != NULL )
+	{
+	    if ( node->snap_shot != NULL )
+	    {
+		free_text_stat (node->snap_shot);
+		node->snap_shot = NULL;
+	    }
+
+	    if ( node->ptr != NULL )
+	    {
+		free_text_stat (node->ptr);
+		node->ptr = NULL;
+	    }
+	}
+
+	destruct_cache_node (text_mcb, i);
+    }
+
+    free_match_table(match_table);
+
+    sfree (match_table);
+    sfree (conf_table);
+}
+
+
+static void
+limit_pers()
+{
+    Cache_node *node;
+    int i;
+    
+    node = pers_mcb->mru;
+
+    /* Skip first CACHE_PERSONS clean persons. */
+    for ( i = 0; node != NULL && i < CACHE_PERSONS; i++ )
+    {
+	while ( node != NULL && node->s.dirty == 0
+	       && node->snap_shot == NULL && node->lock_cnt == 0 )
+	{
+	    node = node->next;
+	}
+	       
+	if ( node != NULL )
+	    node = node->next;
+    }
+
+    /* Delete any remaining clean persons */
+    while ( node != NULL )
+    {
+	if ( node->s.dirty == 0 && node->snap_shot == NULL
+	    && node->lock_cnt == 0 )
+	{
+	    unlink_pers_lru(node);
+	    free_person (node->ptr);
+	    node->ptr = NULL;
+	    /* +++ delete cache-node if non-existent. */
+	}
+
+	node = node->next;
+    }
+}
+
+static void
+limit_conf()
+{
+    Cache_node *node;
+    int i;
+    
+    node = conf_mcb->mru;
+
+    /* Skip first CACHE_CONFERENCES clean confs. */
+    for ( i = 0; node != NULL && i < CACHE_CONFERENCES; i++ )
+    {
+	while ( node != NULL && node->s.dirty == 0
+	       && node->snap_shot == NULL && node->lock_cnt == 0 )
+	{
+	    node = node->next;
+	}
+	       
+	if ( node != NULL )
+	    node = node->next;
+    }
+
+    /* Delete any remaining clean confs. */
+    while ( node != NULL )
+    {
+	if ( node->s.dirty == 0 && node->snap_shot == NULL
+	    && node->lock_cnt == 0 )
+	{
+	    unlink_conf_lru(node);
+	    free_conference (node->ptr);
+	    node->ptr = NULL;
+	    /* +++ delete if non-existent. */
+	}
+
+	node = node->next;
+    }
+}
+
+
+static void
+limit_text_stat()
+{
+    Cache_node *node;
+    int i;
+    
+    node = text_mcb->mru;
+
+    /* Skip first CACHE_TEXT_STATS clean text_stats. */
+    for ( i = 0; node != NULL && i < CACHE_TEXT_STATS; i++ )
+    {
+	while ( node != NULL && node->s.dirty == 0
+	       && node->snap_shot == NULL && node->lock_cnt == 0 )
+	{
+	    node = node->next;
+	}
+	       
+	if ( node != NULL )
+	    node = node->next;
+    }
+
+    /* Delete any remaining clean text_stats. */
+    while ( node != NULL )
+    {
+	if ( node->s.dirty == 0 && node->snap_shot == NULL
+	    && node->lock_cnt == 0 )
+	{
+	    unlink_text_lru(node);
+	    free_text_stat (node->ptr);
+	    node->ptr = NULL;
+	    /* +++ delete if non-existent. */
+	}
+
+	node = node->next;
+    }
+}
+
+
+
+/*
+ * Limit the number of 'clean' cache entries.
+ */
+void
+cache_limit_size(void)
+{
+    limit_pers();
+    limit_conf();
+    limit_text_stat();
+}
+
+  
-- 
GitLab