PennMUSH Community

Changeset 479

Show
Ignore:
Timestamp:
08/16/06 01:46:08 (2 years ago)
Author:
pennmush
Message:

PennMUSH 1.7.7p40 Archival

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • 1.7.7/CHANGES.177

    r477 r479  
    1818 
    1919========================================================================== 
     20 
     21Version 1.7.7 patchlevel 40                     December 1, 2004 
     22 
     23Major Changes: 
     24  * Another pass at the chunk allocator! Simpler but effective. 
     25    Folks should, however, greatly reduce their chunk_migrate 
     26    value in mush.cnf -- we suggest '50'. [TAP] 
     27Commands: 
     28  * @command/alias can alias commands. Patch by Walker@M*U*S*H. 
     29Functions: 
     30  * zwho() and zmwho(). [EEH] 
     31Minor Changes: 
     32  * utils/penn-install is no longer part of the PennMUSH distribution 
     33    (it's part of the Debian maintainer's stuff). [EEH] 
     34  * Inheritable @locks are inherited off of ancestor objects.  
     35    Suggested by Zith@Lovarii. [SW]  
     36Fixes: 
     37  * Infinite recursion in @lock/examine fixed. Report by 
     38    Amy Kou'ai (Amy@ShoujoAi) and Sparta Kerleon (Sparta@ShoujoAi). [TAP] 
     39  * @flag/letter now allows setting a flag's letter to one used by 
     40    another flag that works on different object types. Report by Lenon. 
     41  * Translation corrections by Cheetah@M*U*S*H and [EEH]. 
     42  * Added __USE_POSIX to the cflags for linux, and removed  
     43    checking for -lbind, to help SuSE 9.  Report by Ambrosia@M*U*S*H. 
     44  * Fixes to panic db loading logic. [SW]  
     45  * escape() shouldn't double-escape the first character of the 
     46    string when it's a special character. Report by Walker@M*U*S*H. 
     47 
    2048 
    2149Version 1.7.7 patchlevel 39                     October 25, 2004 
  • 1.7.7/Configure

    r467 r479  
    1919# 
    2020 
    21 # $Id: Head.U 1.1 Thu, 20 Jul 2000 17:42:54 -0500 dunemush $ 
     21# $Id: Configure 1.21.1.4.1.1.1.1.1.1.1.7.1.14 Mon, 28 Jun 2004 09:33:37 -0500 dunemush $ 
    2222# 
    23 # Generated on Mon May 24 11:39:50 CDT 2004 [metaconfig 3.0 PL70] 
     23# Generated on Mon Jun 28 09:20:55 CDT 2004 [metaconfig 3.0 PL70] 
    2424 
    2525cat >/tmp/c1$$ <<EOF 
  • 1.7.7/MANIFEST

    r477 r479  
    164164utils/mkcmds.sh.SH 
    165165utils/mkvershlp.pl 
    166 utils/penn-install 
    167166utils/update-cnf.pl 
    168167utils/update.pl 
  • 1.7.7/Makefile.SH

    r467 r479  
    6767GLOBAL_INSTALL=/usr/libexec/pennmush 
    6868 
    69 # Where to install with 'make debianinstall' 
    70 DEB_INSTALL=$(DESTDIR)/usr/lib/pennmush/game 
    71 DEB_BIN=$(DESTDIR)/usr/games 
    72  
    7369all: config.h options.h autogen game/mush.cnf 
    7470    @echo "Making all in src." 
     
    299295    @echo "** or symlink that to somewhere easier to run. You may wish to strip them." 
    300296 
    301 debianinstall: install 
    302     (cd game/txt; make clean compose.sh) 
    303     $(INSTALLDIR) $(DEB_INSTALL) 
    304     $(INSTALLDIR) $(DEB_BIN) 
    305     $(CP) -R game/* $(DEB_INSTALL) 
    306     -rm -f $(DEB_INSTALL)/netmush $(DEB_INSTALL)/info_slave 
    307     $(INSTALL) config.sh $(DEB_INSTALL)/config.sh 
    308     $(INSTALL) src/netmud $(DEB_INSTALL)/netmush 
    309     $(INSTALL) src/info_slave $(DEB_INSTALL)/info_slave 
    310     $(INSTALL) utils/penn-install $(DEB_BIN)/penn-install 
    311     $(CHMOD) a+rX -R $(DEB_INSTALL) 
    312     $(CHMOD) a+rX $(DEB_BIN)/penn-install 
    313     @echo "** Files installed in $(DEB_INSTALL)." 
    314     @echo "** You can run penn-install to create a user directory." 
    315  
    316297!NO!SUBS! 
    317298chmod 644 Makefile 
  • 1.7.7/Patchlevel

    r477 r479  
    11Do not edit this file. It is maintained by the official PennMUSH patches. 
    2 This is PennMUSH 1.7.7p39 
     2This is PennMUSH 1.7.7p40 
  • 1.7.7/config_h.SH

    r463 r479  
    2626 * For a more permanent change edit config.sh and rerun config_h.SH. 
    2727 * 
    28  * \$Id: Config_h.U,v 3.0.1.5 1997/02/28 14:57:43 ram Exp
     28 * \$Id: config_h.SH 1.17.1.2.1.1.1.11 Mon, 24 May 2004 14:14:15 -0500 dunemush
    2929 */ 
    3030 
  • 1.7.7/confmagic.h

    r337 r479  
    77 * without the -M option. 
    88 * 
    9  *  $Id: Magic_h.U,v 3.0.1.2 1993/11/10 17:32:58 ram Exp
     9 *  $Id: confmagic.h 1.9 Fri, 15 Feb 2002 16:56:28 -0600 dunemush
    1010 */ 
    1111 
  • 1.7.7/game/mushcnf.dst

    r477 r479  
    153153# second.  The higher the value, the faster memory gets defragmented, 
    154154# but at a greater CPU cost. 
    155 chunk_migrate 500 
     155chunk_migrate 50 
    156156 
    157157### 
  • 1.7.7/game/txt/hlp/penncmd.hlp

    r477 r479  
    571571  @command <command> 
    572572  @command/<switch> <command> 
     573  @command/alias <command>=<new command name> 
    573574 
    574575  @command provides information about and controls the availability  
     
    583584  /enable    : Enable the <command> 
    584585  /on        : Synonym for /enable 
     586  /alias     : Creates an alias for a command. 
    585587  /quiet     : Don't make noisy output when doing one of the above 
    586588  /add       : Creates a useless command. @hook/override it. 
    587   /delete    : Deletes a command added by @command/add 
     589  /delete    : Deletes a command added by @command/add, or aliases. 
    588590 
    589591  See HELP RESTRICT for more. 
  • 1.7.7/game/txt/hlp/pennfunc.hlp

    r477 r479  
    114114  cmds()        conn()        doing()       height()      hostname() 
    115115  hidden()      idle()        ipaddr()      lports()      lwho()         
    116   mwho()        ports()       pueblo()      recv()        sent() 
    117   ssl()         terminfo()    width()  
     116  mwho()        nmwho()       nwho()        ports()       pueblo()       
     117  recv()        sent()        ssl()         terminfo()    width()        
     118  xmwho()       xwho()        zmwho()       zwho() 
    118119& Dbref functions 
    119120  Dbref functions return a dbref or list of dbrefs related to some value 
     
    45324533 
    45334534  See also: lwho(), mwho(), nwho() 
     4535 
     4536& ZMWHO() 
     4537  zmwho(<object>) 
     4538 
     4539  This returns a list of the dbref numbers for all current-connected, 
     4540  non-hidden players within a location belonging to the specified zone. 
     4541  It's exactly the same as zwho() used by a mortal, and is suitable for 
     4542  use on privileged global objects who need an unprivileged zwho-list. 
     4543 
     4544  See also: zwho() 
     4545 
     4546& ZWHO() 
     4547  zwho(<object>[,<viewer>]) 
     4548 
     4549  This returns a list of the dbref numbers for all currently-connected 
     4550  players within a location belonging to the specified zone. When mortals 
     4551  use this function, the dbref numbers of DARK wizards or hidden royalty 
     4552  do NOT appear on the dbref list. 
     4553   
     4554  If <viewer> is given by a privileged user, zwho() returns a dbref list 
     4555  using <viewer>'s privileges. 
     4556 
     4557  See also: zmwho() 
    45344558& ZEMIT() 
    45354559& NSZEMIT() 
  • 1.7.7/game/txt/hlp/penntop.hlp

    r477 r479  
    392392  UNIX            Tinyfugue   tf.tcp.com 
    393393                              /pub/tinyfugue 
    394   WINDOWS 32-bit  MUSHClient  ftp.pennmush.org 
    395                               /pub/PennMUSH/Win32Binaries 
     394  WINDOWS 32-bit  MUSHClient  http://www.mushclient.com 
    396395                  SimpleMU    http://simplemu.onlineroleplay.com 
     396                  MuckClient  http://www.xcalibur.co.uk/MuckClient/ 
    397397  MACINTOSH       MUDDweller  http://www.shareware.com (search for Muddweller) 
    398398 
  • 1.7.7/game/txt/hlp/pennv177.hlp

    r477 r479  
    1 & 1.7.7p39 
     1& 1.7.7p40 
    22& changes 
    33This is a list of changes in this patchlevel which are probably of 
     
    1212be read in 'help patchlevels'. 
    1313 
     14Version 1.7.7 patchlevel 40                     December 1, 2004 
     15 
     16Major Changes: 
     17  * Another pass at the chunk allocator! Simpler but effective. 
     18    Folks should, however, greatly reduce their chunk_migrate 
     19    value in mush.cnf -- we suggest '50'. [TAP] 
     20Commands: 
     21  * @command/alias can alias commands. Patch by Walker@M*U*S*H. 
     22Functions: 
     23  * zwho() and zmwho(). [EEH] 
     24Minor Changes: 
     25  * utils/penn-install is no longer part of the PennMUSH distribution 
     26    (it's part of the Debian maintainer's stuff). [EEH] 
     27  * Inheritable @locks are inherited off of ancestor objects.  
     28    Suggested by Zith@Lovarii. [SW]  
     29Fixes: 
     30  * Infinite recursion in @lock/examine fixed. Report by 
     31    Amy Kou'ai (Amy@ShoujoAi) and Sparta Kerleon (Sparta@ShoujoAi). [TAP] 
     32  * @flag/letter now allows setting a flag's letter to one used by 
     33    another flag that works on different object types. Report by Lenon. 
     34  * Translation corrections by Cheetah@M*U*S*H and [EEH]. 
     35  * Added __USE_POSIX to the cflags for linux, and removed  
     36    checking for -lbind, to help SuSE 9.  Report by Ambrosia@M*U*S*H. 
     37  * Fixes to panic db loading logic. [SW]  
     38  * escape() shouldn't double-escape the first character of the 
     39    string when it's a special character. Report by Walker@M*U*S*H. 
     40 
     41 
     42& 1.7.7p39 
    1443Version 1.7.7 patchlevel 39                     October 25, 2004 
    1544 
  • 1.7.7/game/txt/hlp/pennvOLD.hlp

    r477 r479  
    442044201.7.7: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 
    44214421       19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 
    4422        36, 37, 38, 39 
     4422       36, 37, 38, 39, 40 
    442344231.7.6: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 
    442444241.7.5: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 
  • 1.7.7/hdrs/command.h

    r477 r479  
    106106                  char *arg_left, char *args_left[MAX_ARG], \ 
    107107                  char *arg_right, char *args_right[MAX_ARG]) 
    108  
    109 /* For things that DON'T get auto-aliased by mkalias, like 'i' for 'inv' and 'l' for 'look' */ 
    110  
    111 typedef struct command_alias COMALIAS; 
    112 /** An alias to a command. 
    113  * This structure represents a command alias, which consists of the command's 
    114  * real (canonical) name and an alias for that name. 
    115  */ 
    116 struct command_alias { 
    117   const char *name; /**< Canonical command name */ 
    118   const char *alias;    /**< Command alias */ 
    119 }; 
    120108 
    121109typedef struct command_info COMMAND_INFO; 
  • 1.7.7/hdrs/version.h

    r477 r479  
    11#define VERSION "1.7.7" 
    2 #define PATCHLEVEL "39
    3 #define PATCHDATE "[10/25/2004]" 
    4 #define NUMVERSION 001007007039 
     2#define PATCHLEVEL "40
     3#define PATCHDATE "[12/01/2004]" 
     4#define NUMVERSION 001007007040 
  • 1.7.7/hints/linux_2.sh

    r267 r479  
    11nm_opt='-B' 
     2ccflags='-D__USE_POSIX' 
     3libswanted='nsl m c crypt intl resolv' 
    24echo "I suggest using sysmalloc when you edit options.h." 
  • 1.7.7/src/attrib.c

    r477 r479  
    245245  static char name[ATTRIBUTE_NAME_LIMIT + 1]; 
    246246  char *p; 
    247   int control; 
    248   int exam; 
     247  int cansee; 
    249248  int canlook; 
    250249  dbref target; 
     
    254253  visible = (player == NOTHING); 
    255254  if (visible) { 
    256     control = 0; 
    257     exam = (Visual(obj) && 
    258         eval_lock(PLAYER_START, obj, Examine_Lock) && 
    259         eval_lock(MASTER_ROOM, obj, Examine_Lock)); 
     255    cansee = (Visual(obj) && 
     256          eval_lock(PLAYER_START, obj, Examine_Lock) && 
     257          eval_lock(MASTER_ROOM, obj, Examine_Lock)); 
    260258    canlook = 0; 
    261259  } else { 
    262     control = controls(player, obj); 
    263     exam = (Visual(obj) && eval_lock(player, obj, Examine_Lock)); 
     260    cansee = controls(player, obj) || 
     261    (Visual(obj) && eval_lock(player, obj, Examine_Lock)); 
    264262    canlook = can_look_at(player, obj); 
    265263  } 
     
    268266  /* If we can't see the attribute itself, then that's easy. */ 
    269267  if (AF_Internal(atr) || AF_Mdark(atr) || 
    270       !(control || exam || 
     268      !(cansee || 
    271269    (AF_Visual(atr) && (!AF_Nearby(atr) || canlook)) || 
    272270    (!visible && !Mistrust(player) && 
     
    297295      } 
    298296      if (AF_Internal(atr) || AF_Mdark(atr) || 
    299       !(control || exam || 
     297      !(cansee || 
    300298        (AF_Visual(atr) && (!AF_Nearby(atr) || canlook)) || 
    301299        (!visible && !Mistrust(player) && 
  • 1.7.7/src/bsd.c

    r477 r479  
    42774277} 
    42784278 
     4279/* ZWHO() function - really belongs in eval.c but needs stuff declared here */ 
     4280/* ARGSUSED */ 
     4281FUNCTION(fun_zwho) 
     4282{ 
     4283  DESC *d; 
     4284  dbref zone, victim; 
     4285  int first; 
     4286  int powered = (strcmp(called_as, "ZMWHO") && Priv_Who(executor)); 
     4287  first = 1; 
     4288 
     4289  zone = match_thing(executor, args[0]); 
     4290 
     4291  if (nargs == 1) { 
     4292    victim = executor; 
     4293  } else if ((nargs == 2) && powered) { 
     4294    if ((victim = match_thing(executor, args[1])) == 0) { 
     4295      safe_str(T(e_match), buff, bp); 
     4296      return; 
     4297    } 
     4298  } else { 
     4299    safe_str(T(e_perm), buff, bp); 
     4300    return; 
     4301  } 
     4302 
     4303  if (!GoodObject(zone) || !eval_lock(victim, zone, Zone_Lock)) { 
     4304    safe_str(T(e_perm), buff, bp); 
     4305    return; 
     4306  } 
     4307  if ((getlock(zone, Zone_Lock) == TRUE_BOOLEXP) || 
     4308      (IsPlayer(zone) && !(has_flag_by_name(zone, "SHARED", TYPE_PLAYER)))) { 
     4309    safe_str(T("#-1 INVALID ZONE."), buff, bp); 
     4310    return; 
     4311  } 
     4312 
     4313  /* Use lowest privilege for victim */ 
     4314  if (!Priv_Who(victim)) 
     4315    powered = 0; 
     4316 
     4317  DESC_ITER_CONN(d) { 
     4318    if (!Hidden(d) || powered) { 
     4319      if (Zone(Location(d->player)) == zone) { 
     4320    if (first) { 
     4321      first = 0; 
     4322    } else { 
     4323      safe_chr(' ', buff, bp); 
     4324    } 
     4325    safe_dbref(d->player, buff, bp); 
     4326      } 
     4327    } 
     4328  } 
     4329} 
     4330 
    42794331/* ARGSUSED */ 
    42804332FUNCTION(fun_doing) 
  • 1.7.7/src/chunk.c

    r467 r479  
    1515 *  
    1616 * <h3>Basic operation:</h3> 
    17  * The managed memory pool is divided into approximately 64K regions
    18  * Each of these regions contain variable-size chunks representing 
    19  * allocated and available (free) memory.  No individual allocatio
    20  * may be larger than will fit in a single region, and no allocation 
    21  * may be smaller than two bytes.  Each chunk has between two and four 
    22  * bytes of overhead (indicating the used/free status, the size of the 
    23  * chunk, and the number of dereferences for the chunk), and each 
    24  * region has additional overhead of about 32 bytes. 
     17 * The managed memory pool is divided into regions of approximately 64KB
     18 * These regions contain variable-size chunks representing allocated and 
     19 * available (free) memory.  No individual allocation may be larger tha
     20 * will fit in a single region, and no allocation may be smaller than one 
     21 * byte.  Each chunk has between two and four bytes of overhead (indicating 
     22 * the used/free status, the size of the chunk, and the number of 
     23 * dereferences for the chunk), and each region has additional overhead 
     24 * of about 42 bytes. 
    2525 *  
    2626 * Allocations are made with the chunk_create() call, which is given 
     
    7777 * whole. 
    7878 *  
    79  * There are several things that factor into a chunk's happiness. 
     79 * There are two things that factor into a chunk's happiness. 
    8080 * The things that make a chunk unhappy are: 
    8181 * <ul> 
    82  * <li> Having free space both before and after the chunk in its region. 
    83  * <li> Having only one allocated neighbor (or worse, none).  The edges 
    84  *      of a region count as allocated neighbors. 
    8582 * <li> Having a dereference count different from the region average. 
    8683 *      The greater the difference, the more unhappy the chunk is. 
    87  * <li> Being in a sparsely populated region.  The more free space in a 
     84 * <li> Being in a sparsely populated region.  The fewer chunks in a 
    8885 *      region, the more unhappy the chunks in it. 
    89  * <li> Being away from the other chunks migrated at the same time. 
    90  *      If some of the other chunks allowed to migrate are in the same 
    91  *      region as a chunk, then it is happier.  (This is specifically 
    92  *      to improve locality during dumps.) 
    9386 * </ul> 
    94  * None of these factors are absolute; all of them have different weights 
    95  * that add into a general unhappiness for the chunk.  The lower the 
    96  * unhappiness, the better. 
     87 * Neither of these factors are absolute; both of them have different 
     88 * weights that add into a general unhappiness for the chunk.  The lower 
     89 * the unhappiness, the better. 
    9790 *  
    9891 * Over time and usage, the dereference counts for chunks will increase 
     
    10598 * and all chunk dereference counts are halved.  The critical number of 
    10699 * regions is determined based on the cache size and the total number of 
    107  * regions.  In general, period change should be controlled primarily by 
    108  * the frequency of database dumps (which end up incrementing the dereference 
    109  * count on all chunks, and thus all regions).  Given a dump frequency 
    110  * of once per hour (the default), there should be a period change about 
    111  * every 2.6 days. 
     100 * regions.  If you're not using forking dumps, then period change should 
     101 * be controlled primarily by the frequency of database dumps (which end 
     102 * up incrementing the dereference count on all chunks, and thus all 
     103 * regions).  Given a dump frequency of once per hour (the default), there 
     104 * should be a period change about every 2.6 days. 
    112105 *  
    113106 *  
     
    219212#include "conf.h" 
    220213 
     214#include <limits.h> 
    221215#include <string.h> 
     216#include <stdarg.h> 
    222217#include <stdlib.h> 
    223218 
     
    253248/** Log all moves and slides during migration. */ 
    254249#undef DEBUG_CHUNK_MIGRATE 
    255 /** Log start, phases, and finish of migration. */ 
    256 #undef DEBUG_CHUNK_MIGRATE_LOUD 
    257 /** Log info about trying to fill holes. */ 
    258 #undef DEBUG_CHUNK_MIGRATE_FILL 
    259250/** Log creation of regions. */ 
    260251#undef DEBUG_CHUNK_REGION_CREATE 
     
    263254/** Log all mallocs. */ 
    264255#undef DEBUG_CHUNK_MALLOC 
     256 
     257/** For debugging, we keep a rolling log of debug messages. 
     258 * These get dumped to disk if we're about to panic. 
     259 */ 
     260#define ROLLING_LOG_SIZE 200 
     261#define ROLLING_LOG_ENTRY_LEN 1024 
    265262 
    266263/* debug... */ 
     
    291288#define MAX_CHUNK_LEN (16384-1) 
    292289 
     290/** Number of oddballs tracked in regions. 
     291 * This is used to figure out when we should pull regions in because 
     292 * we have an opportunity to migrate chunks that don't match. 
     293 * Relatively arbitrary; too low means you don't move things out 
     294 * enough, but boosting it too high wastes memory. 
     295 */ 
     296#define NUM_ODDBALLS 10 
     297 
     298/** Minimum disagreement to be an oddball. 
     299 * This is used to figure out when we should pull regions in because 
     300 * we have an opportunity to migrate chunks that don't match. 
     301 * Relatively arbitrary; too low means you don't move things out 
     302 * enough, but boosting it too high wastes migration time. 
     303 */ 
     304#define ODDBALL_THRESHOLD 8 
     305 
    293306/* 
    294307 * FIXME: pulling config variables out of my left ear. Fix later. 
     
    299312#define FIXME_REGION_ARRAY_INCREMENT 10 
    300313 
    301 /* 
    302  * FIXME: unhappiness constants pulled out of right ear. 
    303  * Needs testing and tweaking. 
    304  */ 
    305 /** Constants affecting the way things are migrated around. 
    306  * Details in the migration discussion. */ 
    307 #define UNHAPPINESS_HARD 0 
    308 #define UNHAPPINESS_SOFT 4 
    309 #define UNHAPPINESS_MAYBE 32 
    310 #define UNHAPPINESS_TWO 0 
    311 #define UNHAPPINESS_ONE 2 
    312 #define UNHAPPINESS_ZERO 24 
    313 #define UNHAPPINESS_SPACE_DIVISOR 1024 
    314 #define UNHAPPINESS_DEREFS_DIVISOR 1 
    315 #define UNHAPPINESS_NEVER 0xffff 
    316 #define UNHAPPINESS_AWAY_THRESHOLD 96 
     314/** Limit for when being a nearly-empty region counts against being 
     315 * a good region.  This is exponential: an empty region gets a penalty 
     316 * of 1 << LONLINESS_LIMIT.  A near-empty region gets a penalty of 
     317 * 1 << (LONLINESS_LIMIT - used_count). 
     318 * 
     319 * Rationale: we don't want to reuse empty regions (or make new regions) 
     320 * for trivialities. 
     321 */ 
     322#define LONLINESS_LIMIT 5 
     323 
     324/** Free space limit for when we consider making new regions. 
     325 * The total free space must be less than this percent of capacity. 
     326 * 
     327 * Rationale: we don't want to waste memory with lots of extra regions. 
     328 */ 
     329#define FREE_PERCENT_LIMIT 2 
     330 
     331/** Bias for allocating chunks in a region that's already in memory. 
     332 * Actually, this is a bias against allocating in swapped-out regions, 
     333 * but that's a nit... 
     334 * 
     335 * Rationale: reduce the amount of paging during migration. 
     336 */ 
     337#define IN_MEMORY_BIAS 4 
    317338 
    318339/* 
     
    446467  ChunkPointer(ChunkReferenceToRegion((ref)), ChunkReferenceToOffset((ref))) 
    447468 
    448  
    449469/* 
    450470 * Macros for probing and manipulating chunk headers 
     
    501521  ((ChunkDataPtr(region, offset)[0] << 8) + ChunkDerefs(region, offset)) 
    502522 
     523/* 0 for no, 1 for yes with room, 2 for exact */ 
     524#define FitsInSpace(size, capacity) \ 
     525  (((size) == (capacity)) ? 2 : ((size) <= (capacity) - MIN_REMNANT_LEN)) 
     526 
    503527/** Region info that gets paged out with its region. 
    504528 * This is at the start of the region; 
     
    525549                                           counts on period change! */ 
    526550  RegionHeader *in_memory;  /**< cache entry; NULL if paged out */ 
     551  u_int_16 oddballs[NUM_ODDBALLS];  /**< chunk offsets with odd derefs */ 
    527552} Region; 
    528553 
     
    533558     regions[(region)].used_count \ 
    534559   : 0) 
     560#define RegionDerefsWithChunk(region, derefs) \ 
     561   (((regions[(region)].total_derefs >> \ 
     562     (curr_period - regions[(region)].period_last_touched)) + derefs) / \ 
     563    (regions[(region)].used_count + 1)) 
    535564 
    536565/* 
     
    585614static int stat_page_in;        /**< Number of page-ins */ 
    586615static int stat_migrate_slide;      /**< Number of slide migrations */ 
    587 static int stat_migrate_fill_exact; /**< Number of exact hole fillings */ 
    588 static int stat_migrate_fill_inexact;   /**< Number of inexact hole fillings */ 
    589 static int stat_migrate_away;       /**< Number of chunk expulsions */ 
     616static int stat_migrate_move;       /**< Number of move migrations */ 
     617static int stat_migrate_away;       /**< Number of chunk evictions */ 
    590618static int stat_create;         /**< Number of chunk creations */ 
    591619static int stat_delete;         /**< Number of chunk deletions */ 
     
    596624 * migration globals that are used for holding relevant data... 
    597625 */ 
    598 static int m_alloc;     /**< The allocated length for the arrays. */ 
    599626static int m_count;     /**< The used length for the arrays. */ 
    600627static chunk_reference_t **m_references; /**< The passed-in references array. */ 
    601 static u_int_16 *m_length;  /**< The lengths of the chunks to be moved. */ 
    602 static u_int_16 *m_unhappiness; /**< The unhappiness of the chunks. */ 
    603 static unsigned char *m_derefs; /**< The dereferences for the chunks. */ 
    604 static int m_limit;     /**< The number of migrates allowed. */ 
    605  
     628 
     629#ifdef CHUNK_PARANOID 
     630/** Log of recent actions for debug purposes */ 
     631static char rolling_log[ROLLING_LOG_SIZE][ROLLING_LOG_ENTRY_LEN]; 
     632static int rolling_pos; 
     633static int noisy_log = 0; 
     634#endif 
     635 
     636/* 
     637 * Forward decls 
     638 */ 
     639static void find_oddballs(u_int_16 region); 
    606640 
    607641/* 
    608642 * Debug routines 
    609643 */ 
     644/** Add a message to the rolling log. */ 
     645static void 
     646debug_log(char const *format, ...) 
     647{ 
    610648#ifdef CHUNK_PARANOID 
     649  va_list args; 
     650 
     651  va_start(args, format); 
     652  vsprintf(rolling_log[rolling_pos], format, args); 
     653  va_end(args); 
     654 
     655  rolling_log[rolling_pos][ROLLING_LOG_ENTRY_LEN - 1] = '\0'; 
     656  if (noisy_log) { 
     657    fprintf(tracelog_fp, "%s\n", rolling_log[rolling_pos]); 
     658    fflush(tracelog_fp); 
     659  } 
     660  rolling_pos = (rolling_pos + 1) % ROLLING_LOG_SIZE; 
     661#else 
     662  if (format) 
     663    return;         /* shut up the compiler warning */ 
     664#endif 
     665} 
     666 
     667#ifdef CHUNK_PARANOID 
     668/** Dump the rolling log. */ 
     669static void 
     670dump_debug_log(FILE * fp) 
     671{ 
     672  int j; 
     673  fputs("Recent chunk activity:\n", fp); 
     674  j = rolling_pos; 
     675  do { 
     676    if (rolling_log[j][0]) { 
     677      fputs(rolling_log[j], fp); 
     678      fputc('\n', fp); 
     679      rolling_log[j][0] = '\0'; 
     680    } 
     681    j = (j + 1) % ROLLING_LOG_SIZE; 
     682  } while (j != rolling_pos); 
     683  fputs("End of recent chunk activity.\n", fp); 
     684  fflush(fp); 
     685} 
     686 
     687/** Test if a chunk is migratable. */ 
     688static int 
     689migratable(u_int_16 region, u_int_16 offset) 
     690{ 
     691  chunk_reference_t ref = ChunkReference(region, offset); 
     692  int j; 
     693 
     694  for (j = 0; j < m_count; j++) 
     695    if (m_references[j][0] == ref) 
     696      return 1; 
     697  return 0; 
     698} 
     699 
    611700/** Give a detailed map of a region. 
    612701 * Lists pertinent region information, and all the chunks in the region. 
     
    641730    for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 
    642731     offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) { 
    643       fprintf(fp, "chunk: %4s %-6s off:%04x full:%04x ", 
     732      fprintf(fp, "chunk:%c%4s %-6s off:%04x full:%04x ", 
     733          migratable(region, offset) ? '*' : ' ', 
    644734          ChunkIsFree(region, offset) ? "FREE" : "", 
    645735          ChunkIsShort(region, offset) ? "SHORT" : 
     
    678768       pos < REGION_SIZE; pos += ChunkFullLen(region, pos)) { 
    679769    if (pos == offset) { 
    680       if ((ChunkPointer(region, pos)[0] & CHUNK_FREE_MASK) == CHUNK_FREE
    681     mush_panic("Invalid reference to used chunk"); 
     770      if (ChunkIsFree(region, pos)
     771    mush_panic("Invalid reference to free chunk as used"); 
    682772      return; 
    683773    } 
    684774  } 
     775  mush_panic("Invalid reference to non-chunk as used"); 
    685776} 
    686777 
     
    10551146 * \param offset the offset of the hole to use. 
    10561147 * \param full_len the length (including headers) of the space to allocate. 
     1148 * \param align the alignment to use: 0 = easiest, 1 = left, 2 = right. 
    10571149 * \return the offset of the allocated space. 
    10581150 */ 
    10591151static u_int_16 
    1060 split_hole(u_int_16 region, u_int_16 offset, u_int_16 full_len
     1152split_hole(u_int_16 region, u_int_16 offset, u_int_16 full_len, int align
    10611153{ 
    10621154  Region *rp = regions + region; 
     
    10981190 
    10991191  ASSERT(hole_len >= full_len + MIN_REMNANT_LEN); 
    1100   if (rp->in_memory->first_free == offset) { 
     1192  if (!align) { 
     1193    if (rp->in_memory->first_free == offset) 
     1194      align = 1; 
     1195    else 
     1196      align = 2; 
     1197  } 
     1198  if (align == 1) { 
    11011199    rp->free_bytes -= full_len; 
    1102     rp->in_memory->first_free += full_len; 
    11031200    write_free_chunk(region, offset + full_len, 
    11041201             hole_len - full_len, ChunkNextFree(region, offset)); 
     1202    if (rp->in_memory->first_free == offset) 
     1203      rp->in_memory->first_free += full_len; 
     1204    else { 
     1205      u_int_16 hole; 
     1206      for (hole = rp->in_memory->first_free; 
     1207       hole; hole = ChunkNextFree(region, hole)) 
     1208    if (ChunkNextFree(region, hole) == offset) 
     1209      break; 
     1210      ASSERT(hole); 
     1211      write_next_free(region, hole, offset + full_len); 
     1212    } 
    11051213    if (rp->largest_free_chunk == hole_len) 
    11061214      rp->largest_free_chunk = largest_hole(region); 
     
    11341242  int done; 
    11351243 
     1244  debug_log("read_cache_region %04x", region); 
     1245 
    11361246  /* Try to seek up to 3 times... */ 
    11371247  for (j = 0; j < 3; j++) 
     
    11811291} 
    11821292 
    1183 /** Write a region from a file. 
     1293/** Write a region to a file. 
    11841294 * \param fd file to write to 
    11851295 * \param rhp region buffer to use 
     
    11941304  size_t remaining; 
    11951305  int done; 
     1306 
     1307  debug_log("write_cache_region %04x", region); 
    11961308 
    11971309  /* Try to seek up to 3 times... */ 
     
    12441356} 
    12451357 
     1358/** Update cache position to stave off recycling. 
     1359 * \param rhp the cached region to keep around. 
     1360 */ 
     1361static void 
     1362touch_cache_region(RegionHeader * rhp) 
     1363{ 
     1364  debug_log("touch_cache_region %04x", rhp->region_id); 
     1365 
     1366  if (cache_head == rhp) 
     1367    return; 
     1368  if (cache_tail == rhp) 
     1369    cache_tail = rhp->prev; 
     1370  if (rhp->prev) 
     1371    rhp->prev->next = rhp->next; 
     1372  if (rhp->next) 
     1373    rhp->next->prev = rhp->prev; 
     1374 
     1375  if (cache_head) 
     1376    cache_head->prev = rhp; 
     1377  rhp->next = cache_head; 
     1378  rhp->prev = NULL; 
     1379  cache_head = rhp; 
     1380  if (!cache_tail) 
     1381    cache_tail = rhp; 
     1382} 
     1383 
    12461384/** Find space in the cache. 
    12471385 * This is likely to require paging out something. 
     
    12521390{ 
    12531391  RegionHeader *rhp; 
     1392 
     1393  debug_log("find_available_cache_region"); 
    12541394 
    12551395  if (!cache_tail || 
     
    12721412    return cache_tail; 
    12731413 
     1414  rhp = cache_tail; 
    12741415  /* page the current occupant out */ 
     1416  find_oddballs(rhp->region_id); 
    12751417#ifdef DEBUG_CHUNK_PAGING 
    12761418  do_rawlog(LT_TRACE, "CHUNK: Paging out region %04x (offset %08x)", 
    1277         cache_tail->region_id, (unsigned) file_offset); 
    1278 #endif 
    1279   write_cache_region(swap_fd, cache_tail, cache_tail->region_id); 
     1419        rhp->region_id, (unsigned) file_offset); 
     1420#endif 
     1421  write_cache_region(swap_fd, rhp, rhp->region_id); 
    12801422  /* keep statistics */ 
    1281   stat_paging_histogram[RegionDerefs(cache_tail->region_id)]++; 
     1423  stat_paging_histogram[RegionDerefs(rhp->region_id)]++; 
    12821424  stat_page_out++; 
    12831425 
    12841426  /* mark the paged out region as not in memory */ 
    1285   regions[cache_tail->region_id].in_memory = NULL; 
     1427  regions[rhp->region_id].in_memory = NULL; 
    12861428  /* mark it not in use for sanity check reasons */ 
    1287   cache_tail->region_id = INVALID_REGION_ID; 
    1288  
    1289   return cache_tail; 
    1290 
    1291  
    1292 /** Update cache position to stave off recycling. 
    1293  * \param rhp the cached region to keep around. 
    1294  */ 
    1295 static void 
    1296 touch_cache_region(RegionHeader * rhp) 
    1297 
    1298   if (cache_head == rhp) 
    1299     return; 
    1300   if (cache_tail == rhp) 
    1301     cache_tail = rhp->prev; 
    1302   if (rhp->prev) 
    1303     rhp->prev->next = rhp->next; 
    1304   if (rhp->next) 
    1305     rhp->next->prev = rhp->prev; 
    1306  
    1307   if (cache_head) 
    1308     cache_head->prev = rhp; 
    1309   rhp->next = cache_head; 
    1310   rhp->prev = NULL; 
    1311   cache_head = rhp; 
    1312   if (!cache_tail) 
    1313     cache_tail = rhp; 
     1429  rhp->region_id = INVALID_REGION_ID; 
     1430 
     1431  return rhp; 
    13141432} 
    13151433 
     
    13261444  unsigned int shift; 
    13271445 
     1446  debug_log("bring_in_region %04x", region); 
     1447 
     1448  ASSERT(region < region_count); 
    13281449  if (rp->in_memory) 
    13291450    return; 
     
    14241545} 
    14251546 
    1426 /** Compute the expected unhappiness for a chunk in a region. 
    1427  * This is used to figure out which region is the best region to hold 
    1428  * a chunk, either when it is new, or when it's really unhappy where it is. 
    1429  * If the region is in memory, then the free list is searched for a good 
    1430  * place to put the chunk; otherwise an educated guess is made based on 
    1431  * the free count, free bytes, and largest free chunk. 
    1432  * \param region the prospective region to hold the chunk. 
    1433  * \param full_len the length (including headers) of the chunk. 
    1434  * \param derefs the number of dereferences on the chunk. 
    1435  * \return the unhappiness rating if the chunk was placed here. 
    1436  */ 
    1437 static u_int_16 
    1438 predict_score(u_int_16 region, u_int_16 full_len, unsigned char derefs) 
     1547/** Find the oddball chunks in a region. 
     1548 * \param region the region to search in. 
     1549 */ 
     1550static void 
     1551find_oddballs(u_int_16 region) 
    14391552{ 
    14401553  Region *rp = regions + region; 
    1441   u_int_16 score; 
    1442  
    1443   if (rp->free_bytes < full_len) 
    1444     return UNHAPPINESS_NEVER; 
    1445  
    1446   score = 0; 
    1447   if (rp->in_memory) { 
    1448     u_int_16 offset, best_offset; 
    1449     score = UNHAPPINESS_NEVER; 
    1450     best_offset = 0; 
    1451     for (offset = rp->in_memory->first_free; 
    1452      offset; offset = ChunkNextFree(region, offset)) { 
    1453       if (ChunkFullLen(region, offset) == full_len) { 
    1454     score = UNHAPPINESS_TWO; 
    1455     best_offset = offset; 
    1456     if (best_offset == rp->in_memory->first_free) 
    1457       break; 
    1458       } else if (ChunkFullLen(region, offset) >= full_len + MIN_REMNANT_LEN && 
    1459          score >= UNHAPPINESS_ONE) { 
    1460     if (score == UNHAPPINESS_ONE && 
    1461         best_offset == rp->in_memory->first_free) 
    1462       continue; 
    1463     score = UNHAPPINESS_ONE; 
    1464     best_offset = offset; 
    1465       } 
     1554  int j, d1, d2; 
     1555  u_int_16 offset, len; 
     1556  int mean; 
     1557 
     1558  for (j = 0; j < NUM_ODDBALLS; j++) 
     1559    rp->oddballs[j] = 0; 
     1560 
     1561  mean = RegionDerefs(region); 
     1562 
     1563  for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 
     1564       offset < REGION_SIZE; offset += len) { 
     1565    len = ChunkFullLen(region, offset); 
     1566    if (ChunkIsFree(region, offset)) 
     1567      continue; 
     1568    d1 = abs(mean - ChunkDerefs(region, offset)); 
     1569    if (d1 < ODDBALL_THRESHOLD) 
     1570      continue; 
     1571    j = NUM_ODDBALLS; 
     1572    while (j--) { 
     1573      if (!rp->oddballs[j]) 
     1574    continue; 
     1575      d2 = abs(mean - ChunkDerefs(region, rp->oddballs[j])); 
     1576      if (d1 < d2) 
     1577    break; 
     1578      if (j < NUM_ODDBALLS - 1)