/
MAILING #2

-=- New String Manager for Envy (and Merc) -=-

Replacement code for :
str_dup(), free_string(), fread_string()


The new functions are in ssm.c, or you may be extracting it from mail
so name it what you want.

- Edit the Makefile and add ssm.o

Two files need to be modified : db.c, save.c

<<<<<   db.c  >>>>>
  ----
(1) - Comment out the functions str_dup(), free_string(), and fread_string()
      fread_string has comments so be careful to comment in blocks

(2) - Add the function prototypes for init_string_space() and boot_done()
      to the Semi-locals. - string search for 'Semi-loc'
      Also add extern for MAX_STRING which is no lonfer a #define

      Add lines:

===========
extern  int MAX_STRING;
void	init_string_space	args( ( void ) );
void	boot_done		args( ( void ) );
===========

      You can now remove MAX_STRING #define and string_hash table.

Line 189 or so:

REMOVE
===========
#define			MAX_STRING	150000
===========

Line 164 or so:

REMOVE
===========
char *			string_hash		[ MAX_KEY_HASH	     ];
===========

      Or you may want to keep them in case you decide to go back to old
      code (If you do you're nuts :P)

(3) - Go to boot_db() , the first thing in boot_db() is where
      the read-only string space is calloc'd :

===========
    /*
     * Init some data space stuff.
     */
    { 
>       if ( !( string_space = calloc( 1, MAX_STRING ) ) )
>       {
>           bug( "Boot_db: can't alloc %d string space.", MAX_STRING );
>           exit( 1 );
>       }
>       top_string	= string_space;
        fBootDb		= TRUE;
    }
===========

Changes to: 

===========
    /*
     * Init some data space stuff.
     */
    { 
PATCH>  init_string_space();
        fBootDb		= TRUE;
    }
===========

init_string_space() either succeeds or exits.


Now somewhere around line 400:
This is where we declare booting over, set fBootDb to FALSE, etc.


 	fix_exits( );
 	fBootDb = FALSE;
PATCH>  boot_done( );      /* ssm.c destroys the boot hash table */
 	area_update( );


boot_done() destroys the temp boot hash table. This table is created
to allow fast referencing of strings for crunching the string space.
Every string is searched for on bootup and all identical strings
are combined to save RAM. This temporary hash table is vital since
the heap is a linked-list first fit algorithm. Without the hash table
you either get 2 minute boot times or larger heap.


(4) - Now we have the functions in place.
      There are still some reliances on strings never being freed.
      Functions like create_mobile() just assign the pointers
      instead of calling str_dup(). That USED to be OK but now the
      str_dup() is real so we have to call it. All this really does
      is updates the usage counter on the string so it won't be freed
      with references still pointing to it. fread_string() is fine since
      the new fread_string() returns a str_dup'd string.

First in create_mobile():

===========
>   mob->name 		= pMobIndex->player_name;
>   mob->short_descr    = pMobIndex->short_descr;
>   mob->long_descr     = pMobIndex->long_descr;
>   mob->description    = pMobIndex->description;
===========

changes to str_dup's

===========
    mob->name 		= str_dup( pMobIndex->player_name );
    mob->short_descr    = str_dup( pMobIndex->short_descr );
    mob->long_descr     = str_dup( pMobIndex->long_descr );
    mob->description    = str_dup( pMobIndex->description );
===========

Then in create_object():

===========
>   obj->name		= pObjIndex->name;
>   obj->short_descr	= pObjIndex->short_descr;
>   obj->description	= pObjIndex->description;
===========

changes to str_dup's

===========
    obj->name		= str_dup( pObjIndex->name );
    obj->short_descr	= str_dup( pObjIndex->short_descr );
    obj->description	= str_dup( pObjIndex->description );
===========


Since my manager doesn't do hashing after bootup to merge matching
strings, there is another loose end. The mob prompts are str_dup'd
from a const char string which creates new space every time so we need
to create a global pointer to a str_dup'd mob prompt and in every
create_mobile, str_dup the pointer rather than a const string.
This is not required but it saves 50k on bootup and even more
when mobs start growing. This was not needed with Furey's code
since it does hashing and always looks for matches.

Somewhere in db.c (mine is right below the declaration for str_empty[1])
we add a global char *:

Around line 175:

PATCH> char *			mobPrompt;

Now add the str_dup in boot_db)()

Around line 416:

>	load_notes( );
>	load_down_time( );
PATCH>  mobPrompt = str_dup( "<%hhp %mm %vmv> " );

Then in create_mobile change the prompt creation from:

	mob->prompt = str_dup( "<%hhp %mm %vmv> " );

To:

PATCH> 	mob->prompt = str_dup( mobPrompt );



NOTE:  In ssm.c you probably need to tweak MAX_STRING some.
       I set it to 1700000 because not only does my code take a little
       more space on the heap but it is can now be used in place of
       the real C strdup() so leave some work space.


<<< save.c >>>


fread_obj() at line 825 of save.c of Envy_1.0

In the block where we read the "End" string of the current
object, compare the strings to the index. If they are identical
then free the obj-><str> and str_dup the obj->pIndexData-><str>

Add it after line 825. (or whatver yours is)

Line 825:             obj->pIndexData->count++;
>                     if ( !strcmp( obj->name, obj->pIndexData->name ) )
>                     {
>                        free_string( obj->name );
>                        obj->name = str_dup( obj->pIndexData->name );
>                     }
>                     if ( !strcmp( obj->short_descr, obj->pIndexData->short_descr ) )
>                     {
>                        free_string( obj->short_descr );
>                        obj->short_descr = str_dup( obj->pIndexData->short_descr );
>                     }
>                     if ( !strcmp( obj->description, obj->pIndexData->description ) )
>                     {
>                        free_string( obj->description );
>                        obj->description = str_dup( obj->pIndexData->description );
>                     }

That should save some mem especially if your mud allows packratting.


After recompile type 'mem' in the game. Your perm count should be lower
and string count should be almost identical to the old code.

-==-

This is all that needs to be changed in the base Envy and it should be
identical for Merc. I have no idea what ROM's string code is like so
I can't say, but if it is the standard no-freeing Merc code then you
may want to think about adding my patch. Using OLC now should have
no bearing on the runtime (gradual buildup of read-only strings).
The latest version of ssm.c should be with Jason Dinkel's ILAB OLC.

Let me know if you have problems or if I missed something.
Lost Realms has been running for 3 months with this code and OLC
with no problems.

Fusion
msmith@falcon.mercer.peachnet.edu