tinymush-3.0b21/game/bin/
tinymush-3.0b21/game/data/
tinymush-3.0b21/src/tools/
Frequently-Asked Questions
==========================

- I found a bug! What do I do?
- How do I make a new configuration file?
- How do I back up my database?
- How do I restore a database backup?
- How do I apply a patch upgrade or bugfix?
- How do logfiles work?
- How do I use multiple guests?
- How do I tune the database cache?
- How do I use radix compression?
- How do I use an in-memory database?
- Help! I'm having database problems.
- How do I set up a link to an external SQL database?

------------------------------------------------------------------------------

I found a bug! What do I do?

- Make sure that it really is a bug, and not a new feature or design
  decision. If it crashes the server, it's a bug. If you can't tell,
  consider it a bug.

- Try to come up with an easily-reproducible sequence of events that
  will demonstrate the bug.

- Send email to tinymush-bugs@godlike.com with the bug report.

- If the bug crashes the server, we really, really, want to hear about
  it. We'd like as much information as possible.

  We've included a script which automatically analyzes core files and
  emails results to us. Go to your game directory, and type './ReportCrash'
  You should eventually see a 'Done.' -- that means the analysis was
  successful. If you get an error message and early end to the script,
  you'll need to deal with it manually.

  The following sequence of commands will generate a stack trace and
  variable dumps from the core file. Cut-and-paste the output and
  email it along with your bug report. You can obtain this by doing
  the following from the game directory:

  gdb bin/netmush core
	where
	info frame
	info args
	info locals
	up
	info args
	info locals
	up	(Repeat until you're at the top procedure level.)
	quit

  If you don't have gdb, use dbx, as follows:

  dbx bin/netmush core
	where
	dump
	up
	dump
	up	(Repeat until you're at the top procedure level.)
	quit

------------------------------------------------------------------------------

How do I make a new configuration file?

TinyMUSH 3.0 gets the information it needs to operate the game (aside from
the database itself) from a configuration file that is read in at startup.
The configuration file contains various parameters, such as where to find
the database, what port to listen for connects, and many other things.

Follow these instructions to make a configuration file for your MUSH from
the supplied template configuration file:

In your game directory, copy the file netmush.conf to <your-mud-name>.conf
and edit it as follows:

    - Replace netmush.<whatever> in the 'xxx_database' lines with
      <your-mud-name>.<whatever>.

    - Set the port number on the 'port' line to the correct port.

    - Set the mud name on the 'mud_name' line to the name of your mud.

    - Make any other configuration changes you want to make at this time.
      Here are some of the common ones to change:
         o money_name_singular <text>  The name of one coin (penny)
         o money_name_plural <text>    The name of several coins (pennies)
         o fork_dump no           Do this if you have little swap space.
         o paycheck <amount>      Players get this much money each day
                                  they connect.
         o paystart <amount>      Players start out with this much money.
         o payfind <chance>       Each time a player moves, he has a
                                  1 in <chance> chance of finding a penny.
         o player_starting_room <roomno>  The room that new players are
                                  created in.

There are many more configuration directives available. Information
on individual directives can be obtained with the WIZHELP <directive>
command within the MUSH.

------------------------------------------------------------------------------

How do I back up my database?

Shut down your game. Go into the game directory, and type './Backup'
You can safely back up your database while the game is running; if you
do this, do a @dump, wait a minute until the database is done saving,
and then run the backup.

This will create a 'flatfile', and compress it with GNU zip; if there's
no GNU zip on your system, you should edit the Backup script so it uses
Unix compress instead.

Do NOT simply naively copy around netmush.db, netmush.gdbm, etc., as
they are not portable between platforms. Use the Backup script to
create flatfiles.

Note that this does NOT back up your comsys database or mail database.
You can simply copy comsys.db and mail.db to a safe place, to back
them up.

------------------------------------------------------------------------------

How do I restore a database backup?

Shut down the game (if it's currently running). Then, go into the game
directory and type './Restore name-of-flatfile', where name-of-flatfile
is the name of your backup file.

Note that this only restores your database; it does not restore the
comsys or mail databases. To restore the latter, simply copy your
saved copies of comsys.db and mail.db back to the game directory.

------------------------------------------------------------------------------

How do I apply a patch upgrade or bugfix?

To patch the server:

- Download the patch from the archive, via FTP or the Web. Save the file
  in your code directory, which is probably called something like
  'tinymush-3.0' -- it's the same directory that contains this FAQ file.

- Type:  gzcat name_of_patchfile.gz | patch -p1
  name_of_patchfile will probably be something like 'patch-30p1-30p2'
  (with a .gz extension).
  If you do not have gzcat, type 'gunzip name_of_patchfile.gz' and then
  'patch -p1 < name_of_patchfile'
  If you do not have patch, you cannot apply patches. Get your system
  administrator to install it.

- Type:  ./Build

If there are problems with the patch, make sure that nothing strange
has happened -- for example, there are no carriage-return/newlines ('^M')
characters at the end of lines.

Also, if you're applying multiple patches, make sure to do them in 
chronological sequence -- oldest to newest patch.

------------------------------------------------------------------------------

How do logfiles work?

When you start your game from the command line, the startup information
is logged to GAMENAME.log, where GAMENAME is what you specified it to
be in your mush.config file.

Subsequently, log information is written to whatever you set your
game_log configuration parameter to be in your GAMENAME.conf file
(whatever GAMENAME is); if you didn't specify that parameter,
'netmush.log' will be used. In general, you will probably want to set
it to GAMENAME.log, so startup information and regular log information
are all written to the same file.

You can separate log information of different types into multiple
files, using the divert_log configuration parameter. See the wizhelp
for details.

When you @restart, or do a @logrotate, the existing logfiles are closed
and renamed to LOGNAME.TIMESTAMP, where LOGNAME is the name of the log,
and TIMESTAMP is the "epoch time" (equivalent to the number of seconds
returned by the secs() MUSH function). You can delete those logfiles
to reclaim disk space, if you'd like. The current logfile will always
have the "standard" name as specified by the game_log and/or divert_log
parameters, though.

When you start the game from the command line, any existing GAMENAME.log
file will be moved to GAMENAME.log.old -- but logs from any divert_log
directives will not be renamed in this way.

Thus, it's a good idea to go through your game directory on a periodic
basis, cleaning out old logs.

------------------------------------------------------------------------------

How do I use multiple guests?

Using multiple guests is easy, and after you set it up, you'll never have to
worry about it again. Here are the steps needed to implement multiple
guests:

1. @pcreate a prototype guest character. Name it whatever you want (altho
you should use a descriptive name like 'Guest'), and use any password you
want (it doesn't really matter, as the prototype guest can never connect).
Set guest_char_num to the database number of the prototype guest character.

2. You may want to set the following things on the prototype guest
character, which are inherited by every guest character: the amount of
money, the zone, the parent, the basic lock, the enter lock, and all
attributes. (NOTE: Guests always start off in the room specified by the
player_starting_room).

3. Set the config parameter 'guest_prefix' to whatever you want your guests
to be named (this defaults to 'Guest'). MUSH keeps track of multiple guests
by naming them using a numbering system: <prefix><number>. For example,
Guest1, Guest2, Guest3, etc. People who wish to connect as a guest will have
to use this prefix, for example, if 'guest_prefix' was set to 'Visitor', one
would have to type 'connect visitor' to log in as a guest.

4. Set 'number_guests' to the maximum number of guests you wish to support.
This number can be as small or as large as you wish.

5. Optionally, set 'guest_nuker' to a wizard's database number, if you wish
to have a wizard other than #1 to nuke the guests.


The file specified by the config parameter 'guest_file' is shown to every
guest when they connect. You may wish to use the 'access' config parameter
to bar guests from using certain commands, using the 'no_guest' permission.
All guests have the 'Guest' power, which is a marker you may use to test
whether a player is a guest or not.

------------------------------------------------------------------------------

How do I tune the database cache?

Hi. Andrew Molitor here. I am not exactly an expert on cache tuning, but
then, nobody is. It's something of a black art. The basic tradeoff here is
this: If you make your cache larger, it will consume more memory, but you
will have to make disk accesses less often to get data. This sounds great,
until you remember that if you consume *enough* memory, the operating system
will begin to page random bits of your game on and off of disk -- you are
better off staying small enough to not have that happen, and do your own
getting data on and off disk.

So, you want your cache as large as possible until it gets Too Large, which
is usually when you begin to page too much (more hard page faults in the
output on @list process than I/O in the read column on @list db_stats is a
reasonable guideline. Ideally many fewer page faults), or when your sysadmin
comes pounding on your door wondering what that ENORMOUS process is you have.

What about depth and width? Well, the wider it is, the faster you'll look
things up in it, but the shallower it is, the more it will tend to 'stretch'
outside the specified size. As a guideline, a depth of 9 or 10 seems to be
minimal, and for a few hundred wide, make it at least 15 deep. That's for
object level caching (recommended). For attribute level cacheing, make it,
oh, 50 percent deeper?

There are some statistics you should be aware of:

   - paging -- the hard page faults field of @list process cache hit
     ratio. The percentage of total reads (ignore writes, they rarely
     amount to anything) which require I/O. See @list db_stats for these
     numbers, the 2nd column is where to look. Total calls and I/O are the
     numbers to be looking at.

   - cache size -- this is right at the bottom of the output from @list
     db_stats.

If your cache size is, after running a bit, larger than the original depth X
original width, your cache is 'stretching', and is probably too shallow, and
possibly too small.

If you are making a lot of page faults, your process size is too large, try
shrinking the cache, or filtering out unused attributes, or both, to shrink
process size.

If your cache hit ratio is under about 95-97 percent, your cache is probably
too small, and it should grow. Either wider or deeper, wider is preferable
unless your cache tends to stretch, see above.

It's a careful dance you need to do, so watch the statistics, and don't be
afraid to try tinkering with the cache size this way and that. Note that
under SunOS (and SysV?) doing I/O will tend to generate page faults as well,
so shrinking your cache may force the database to do more reading and writing
of the disk, and actually increase the number of page faults! So don't just
twiddle a parameter and call it done, watch those numbers!

Good luck ;)

------------------------------------------------------------------------------

How do I use radix compression?

(Contributed by Andrew Molitor.)

NOTE:   You should not use radix compression unless you have a relatively
        large database, consisting of a few hundred objects. Those starting
        from scratch should NOT use compression.

	Using compression is something you don't want to take lightly.
It's useful if you're short on disk space in disk based mode, and it will
help slightly on memory usage as well, but it will cost a little performance.
Not a lot, there is some question about whether the users can feel it at all
on the dinky little Sun 3/60 I run my MUSH on, so it's likely that nobody
will even notice on a normal machine. Benchmarks indicate about a 5%
performance hit. The larger issue is that it's a bit of a hassle to set up.


1. You need to produce a compression table. The radix tree compression
library works by converting common substrings into 12 bit code, so it needs
to know what your common substrings are. You'll need a flat dump of your
database, or at least the ability to produce one. In the radixlib directory,
do a 'configure' then a 'make a' which builds the binary part of the tools
used to analyse your flat dump. Then you run your database through the
analyse.sh shell script, like this:

cat my_db.flat | analyse.sh

	or possibly these variations:

db_unload my_game.gdbm | analyse.sh
zcat my_db.flat.Z | analyse.sh

	This will a) take a while and b) produce a file called compresstab.h.
You can look at it if you like, it's just a big C structure with 4000ish
of the most common strings in your database. If you have access to a big
machine for one-off jobs, I highly recommend using this machine to build
your compression table. Ignore any messages about broken pipes if
compresstab.h exists.

2. Build the compression library. Just do a 'make libcompress.a' in
the radixlib subdirectory.

3. Rebuild your server. Edit the Makefile section called 'Radix
Compression', uncommenting the necessary defines, and rebuild netMUSH
from scratch. Make damn sure have a copy of dbconvert that does not use
compression. Use it to get a flat dump of your uncompressed DB before moving
on.

4. Reload your database compressed. Use the rebuilt dbconvert, it will
now load/unload into/out of a compressed gdbm database. Its flat dump format
is still uncompressed, however. db_load or whatever your poison is to load
up the gdbm database from the flat dump. You're ready to roll!

------------------------------------------------------------------------------

How do I use the in-memory database?

If you're starting your MUSH from scratch, all you need to do is specify in
the Makefile whether you want to be disk based or memory based, and compile,
following the instructions for creating a database. Converting from disk
based to memory based, and vice versa, is a bit more difficult.

Converting from memory based to disk based:
------------------------------------------

It is simple to convert your database to a disk based format, as
follows: recompile with the the disk based options set in the Makefile.
start up the game, log in as a wizard, and shut it down.

Converting from disk based to memory based:
------------------------------------------

You need to use db_unload to convert your gdbm database to a flatfile, as
follows:

	db_unload <gamename>.gdbm <gamename>.db.new <gamename>.db.FLAT

You then need to remove <gamename>.db.new, <gamename>.db,
<gamename>.gdbm.db, and <gamename>.gdbm. When that is done, rename
<gamename>.db.FLAT to <gamename>.db.new. Start up the game.


A comparison of disk based and memory based database storage methods.
--------------------------------------------------------------------

1. Memory based:

- Advantages:
 	- Eliminates the overhead of caching, and accessing the disk to
	  read and write data.
	- Total database usage on disk is usually smaller that a disk-based
	  setup.
	- A memory based setup dumps and loads using a flatfile, which is
	  easier to manage and easily compressible when dumped by the MUSH.
- Disadvantages:
	- Memory usage grows as the size of the database grows.

2. Disk based:

- Advantages:
	- Uses a fixed amount of memory independent of database size.
	- Faster database saves.
- Disadvantages:
	- Slower performance due to the overhead of caching, and getting
	  bits of data to/from disk.
	- Uses 3 files for the database, and usually takes up more disk
	  space than a memory based system, and the main text database is
	  not compressible at dump time.

Memory based usage is preferred _if_ you have enough memory to support a
growing database, however, when memory is at a premium and memory usage is
the key point of whether you remain on your site or not, disk based usage is
the way to go.

Saving disk space:
-----------------

- If you are using a disk based setup, consider converting to a memory based
  setup, which is much more efficient with disk space.
- Enabling the config parameter 'compression', and specifying a
  'compress_program' and 'uncompress_program' will save disk space under
  memory based usage and disk based usage, but it makes much more of a
  difference with memory based because it compresses the entire database.
- Enabling radix compression (see README.COMPRESSION) will reduce the size
  of a disk based database AND its memory usage. On a memory based setup, it
  will only reduce memory usage.

Saving memory:
-------------

- If you are using a memory based setup, consider converting to disk based.
- On a disk based setup, reduce the size of the cache, preferrably making it
  narrower (see README for tips on the cache)
- On both disk and memory based setups, enable radix compression (see
  README.COMPRESSION)
- Adjust HASH_FACTOR in config.h: 2 is recommended, altho 1 is usable and
  results in less memory usage.
- Adjust OUTPUT_BLOCK_SIZE in config.h: this should be a power of 2,
  preferably in the ranger of 4096 to 16384. Any value over the config
  parameter 'output_limit' is wasted.


You should juggle these options until you find a setup that works, and gives
you the best performance. There is no 'right' way to set up a MUSH, it always
depends on the capabilities of the system you are running on, and how much
of those capabilities you can use.

Memory debugging:
----------------

If you turn on malloc debugging in the Makefile (-DMCHECK) you have a wide
range of information to use in hunting down memory leaks or corruption.
@stats/all displays statistics on memory usage. This is useful to check
before and after executing a command to see if it leaks memory (altho you
need to do it multiple times to make sure it's really leaking).

It also enables memory tracing, where all allocation information is written
to a file called mtrace.out in the game directory. The awk script mtrace.awk
is included and analyzes mtrace.out for potential problems.

------------------------------------------------------------------------------

Help! I'm having database problems.

Almost everyone who runs a MUSH experiences a database disaster at
least once in their life. There can be many reasons for this; common
ones include an NFS server dying, running out of disk space,
overflowing your disk quota, a nasty game crash, and a nasty system
crash.

Typically, in this scenario, the server process either dumps core during
an attempt to load the database, or simply hangs; sometimes, it may come
back up and large chunks of your data may be missing.

Sometimes, simply by flatfiling and reloading the flatfile (doing a
Backup and a Restore), integrity issues that cause the database to
fail to load can be dealt with. Be aware that you might experience some
minor data loss in the process, though.

However, your best bet in this scenario is to restore your database
from backup. This means it's very important to keep backups; we strongly
recommend that you back up once a week at minimum, if not nightly.

------------------------------------------------------------------------------

How do I set up a link to an external SQL database?

There is built-in support in TinyMUSH 3.0 for connecting to an external
mSQL database. If you want to do this, you'll need to compile in the
appropriate file (see the Makefile for how to do this).

You can also look at db_sql.h and db_msql.c for examples of how to
write your own method of connecting to another type of external SQL
database. If you do this, please let us know, and provide us with a
copy of the code, so it can be included with the next TinyMUSH relese.

You'll need to have an mSQL 2.x database set up. mSQL can be obtained
from http://www.hughes.com.au/ together with the appropriate documentation.
We do not support the mSQL package itself; if you need help with mSQL
installation, configuration, and maintenance, please refer to the
mSQL pages for assistance.

If the mSQL database is on the same machine as your MUSH, the sql_host
parameter in your netmush.conf file (or equivalent) should be set to
"localhost", so the local Unix domain socket is used; if the database
is not on the same machine as your MUSH, the sql_host parameter should
be whatever the remote server's hostname is.

You then need to create a database in mSQL for the MUSH to use (or
you can, of course, use an existing database). You can do this with:

msqladmin create MUSH_DB

... which creates a database called MUSH_DB. You can then add the
parameer 'sql_database MUSH_DB' to your netmush.conf file.

Make sure that you set up your mSQL installation's msql.acl file
correctly and with the appropriate level of security. See mSQL's
own documentation for assistance with this.

The database link should come up automatically when the game is
first started. You should see logfile messages that look something
like this, after the 'Load complete.' note in the log:

990831.115339 TinyMUSH SQL/CONN : Connected to SQL server.
990831.115339 TinyMUSH SQL/CONN : SQL database selected.

You should then be able to use the SQL() function from within the MUSH
to make queries against this database. Note that users of this function
need to have the use_sql power.

------------------------------------------------------------------------------
    If you have suggestions for more FAQs, please email us and let us know.
------------------------------------------------------------------------------