1.46: 2006-08-10

    -- fix Mart's broken win32 support that broke Unix, part 2:  syslog when
       daemonized.  TODO: test case should test daemonization mode.

1.45: 2006-08-10

    -- fix Mart's broken win32 support that broke Unix.  TODO:  test to raise/check
       fd limit so this doesn't happen again on unix.

1.44: 2006-08-10

    -- allow a no-op ?foo at the end of concatenated-get URLs, so they'd be of
       the form:  http://host/dir??file1,file2,file3?noopsection.  the no-op
       section is good for cache-busting, putting in, say, the modtime of the
       newest file, forcing browsers like safari (who over-cache) to reload.

    -- set a mime-type other than text/plain on concatenated-get requests,
       only falling back to text/plain if none of files have a known mime type.
       in practice a request is all css or all js, so match is found by looking
       at 1st file.  this is required since mozilla won't show CSS if not text/css.

    -- actually be able to start up using 'perlbal' command.  test
       suite passed before, but moving $VERSION into Perlbal.pm
       had quitely broke it all.

1.43: 2006-08-09

    -- there's a case where offset gets past end of file in static file
       code, but very rarely.  sendfile handles this w/ an error that
       we dealt with, but the new readahead code didn't and crashed.
       working around for now, until root cause is found for offset
       going past.

    -- eliminate some warnings in error cases.  only really affects noise
       in test suite

    -- work better on win32

    -- added the ability for plugins to create custom service roles and
       add custom configuration options to services, demo is available
       as conf/echoservice.conf and lib/Perlbal/Plugin/EchoService.pm

1.42: 2006-08-03

    -- debug management command 'varsize' to track size of internal
       data structures, to make sure none get out of control.
       there's a report that CPU/mem grow slowly over time, and after
       a month or so of uptime, a restart is needed.  this might help
       diagnose that.

    -- allow expansion/interoplation of stuff in config files/commands.
       for now just mapping network device names to IP addresses:
          SET listen = ${ip:eth0}:80

    -- more hooks as requested by community

    -- concatenated get feature.  where a client have use a
       comma-separated list of files to return, always in text/plain.
       Useful for webapps which have dozens/hundreds of tiny css/js
       files, and don't trust browsers/etc to do pipelining.
       Decreases overall roundtrip latency a bunch, but requires app
       to be modified to support it.  See t/17-concat.t test for

    -- do AIO readahead before sendfile to reduce blocking caused
       by disk reads from sendfile.  increases throughput.  see:

    -- add 'latency' configuration on selector roles

1.41: 2006-02-06

    -- IE sends a request header like "If-Modified-Since: <DATE>;
       length=<length>" so we have to remove the length bit before
       comparing it with our date then we save the length to compare

    -- support for reproxying to a named service.  if backend returns
       "X-Reproxy-Service: <name>" and no content, the entire original
       client GET/HEAD request is re-sent to the new named service.
       the "enable_reproxy" option has to be enabled for the original

1.40: 2006-01-17

    -- support for optional retrying of requests after a 500 error,
       so user won't see the 500 error.  boolean option, as well
       as configurable schedule of how often to retry backends.

    -- clean up directory indexing HTML: Mark Smith and Fred Moyer

1.39: (beta for 1.40) 2005-10-26

    -- new feature for virtual host plugin:  the Host header can be trumped
       by a magical URL form, if allowed in config.  for instance, you can
       make an HTTP request to host "foo.com" but actually get "bar.com"
       if you do this:

          VHOST foo.com;using:bar.com  = bar

       and request /__using/bar.com/IDENT from foo.com, where IDENT is
       just \w+.  perlbal then updates the Host record to bar.com and
       sends request URI (unaltered) to the "bar" service.

       this is useful for circumventing browser host restrictions (java,
       javascript, flash, etc...) when you actually control both

1.38: (beta for 1.40) 2005-10-19

    -- some paranoia evals around some parts of buffered uploads that
       SAPO reported crashes in occasionally.  added FIXMEs to investigate
       too.  for now, though, evals around closing files is safer.

    -- new feature: inter-perlbal upload tracking.  for fancy upload
       bars driven by XmlHttpRequest when clients are upload large files

    -- WARNING: reproxying (files or URLs) is now disabled by default,
       and must be enabled per-service with "enable_reproxy = true"

    -- do a final little read before closing an HTTP connection
       to make sure we have no unread data in kernel (notably
       an extra "\r\n" from an IE post), so when we do close, we
       don't send a RST packet to the end user.  Thanks to Kevin
       Lewandowski from discogs.com for the bug report.

    -- use Danga::Socket's AddTimer interface to disconnect
       stale persistent connections every 5 seconds, driven by
       a timer, rather than every 15 seconds, driven by
       socket creation.

    -- there was a bug where 304 Not Modified responses would
       cause a connection close (and thus RST packets) even
       though keep-alive was negotiated and would've worked

    -- ignore URL arguments when doing directory indexing

    -- work a little better under "trickle".  (but still not perfect...
       trickle doesn't quite work on Perlbal, unfortunately. it's useful,
       or would've been useful, for testing some parts...)

    -- avoid an occasional warning with dirindexing on unreadable directories

1.37 (beta for 1.40) 2005-08-29

    -- "use <name>" command to set the direct object for future commands

    -- AccessControl plugin to allow/deny by default or on IPs or

    -- ClientManage could spin in its inherited event_write, causing
       99.9% cpu usage.  Bug is arguably Danga::Socket's, but also
       ours because it's documented what we should do and we didn't.
       The fix is to shut down watching writability when we're done

    -- make accept_client and its callers deal with the possibility
       that accept_client fails not because the backend is bogus, but
       because the client is.  so now accept_client can close the
       client and callers have to be aware of that.

    -- after running this version on production on LiveJournal.com for
       a bit, we discovered some cases that we'd flag as should never happen,
       but actually do, so updated the comments and behavior to
       do the right thing and not just crash with an assertion.

    -- fix misspellings of trusted_upstream_proxies that didn't
       come along for the renaming ride earlier

    -- webserver mode now ignores URL arguments when looking up

    -- remove warnings accessing undefs in ranges and vhosts

    -- new --version and --help flags.  also a usage message on bogus
       options (or when --help).  props to Jacques Marneweck
       <jacques@powertrip.co.za> for the help and motivation.

1.36 (beta for 1.40) 2005-08-19

    -- fix bug in ClientProxy when user disconnects after POST/PUTing
       a content body, but before a response comes back.

    -- now checks correctly for Danga::Socket version 1.44 or above.
       (required version was in quotes, confusing perl.)

    -- vhost plugin: strip off port specification from the Host header
       before trying to match with configured patterns.

1.35: (beta of 1.40) 2005-08-16

    -- beta SSL support in a few lines of code.  maybe it's completely
       done.  maybe it's barely done.  But it seems to work?  I'm no
       SSL master... IO::Socket::SSL just made it so easy.

    -- lots more tests

    -- lots more cleanup

    -- fix potential crashing bugs in the PUT path.  luckily ones we
       never hit.

    -- lots and lots of code cleanup

    -- load plugins by either the exact case specified, all lowercase,
       or all lowercase with first letter uppercase.  then remember
       the case for unloading (which was never implemented?)

    -- reorganize/cleanup code related to stalling the backend due to
       client's buffer size exceeding one of the two limits.
       introduce "backend_stalled"

    -- buffer uploads to disk

1.3: (2005-06-26)

    -- introduce CommandContext, so management commands can be less
       verbose when in config files (service/pool names can be left off
       when you just created them a couple lines before)

    -- remove sendstats support

    -- exit with 0 vs non-zero when/if Perlbal crashes.  new command
       "crash" to fake a crash, for testing.

    -- entirely redone management command parsing/dispatching (major
       code cleanup)

    -- virtual host plugin on service selector framework

    -- service selector framework

    -- make Net::Netmask optional

    -- byte range support for both webserver mode and reproxy-file mode
       Giao Phan <giao@guba.com>.  so clients can resume large transfers.

    -- test suite

    -- IO::AIO support (brad)

    -- change response code to client to 200 on reproxy-file from backend

    -- 'nodes' command now takes as an optional argument a specific ip:port to
       dump the node stats for

    -- AIO abstraction layer (Perlbal::AIO) which can currently do either
       Linux::AIO or "none" (doing everything sync).  also in future File::FDpasser
       and other OS-specific modes [brad]

    -- add buffer_backend_connect to do in memory buffering of data before we
       request a backend; assists slow clients without tying up a mod_perl

    -- fix spinning issue when webnodes unavailable; should now not consume 100%
       CPU in those cases

    -- revamp verbose functionality; by default it's still of, but if you specify
       VERBOSE ON in the config file, it turns it on for management connections
       by default.  management connections, when specifying VERBOSE ON/OFF, will
       now set the flag only for that connection.

    -- new command for config file; VERBOSE ON/OFF; can be used to enable or
       disable confirmation of all commands such as SET, SERVER, CREATE, etc.
       by default, it's off for config files, but on for management connections.

    -- add generation count to services that increments every time a pool is
       switched.  this data is now stored on backends when they're spawned as
       well, and when we allocate a backend we verify the generation so old ones
       are thrown away.

    -- allow setting of nodefile on pools to 'none' or 'null' or 'undef' or just
       an empty set of quotes ("", '') in order to stop using node files

    -- automatically set use count to 0 on new nodes coming in from nodefile

    -- made auto-vivification of pulls throw warnings, and made Perlbal die if it
       tries to vivify a pool and the user has previously manually declared a pool

    -- updated pool commands to be more flexible (POOL pool ADD node, etc)

    -- add pools; a way of having different sets of nodes and instantly switching
       between them, so traffic stops going to old nodes; see the example config
       file for usage

    -- work partially without Linux::AIO (does sync stat of node file in reverse
       proxy mode, and webserver mode doesn't work) --brad

1.2 (2005-03-07)
    -- add new stats command 'nodes' that shows information on each node that we've
       been connecting to -- last connect time, last attempt time, a breakdown of
       the last 500 status codes returned, etc

    -- add ability to use new Danga::Socket profiling; 'profile on', 'profile data'
       to see the info so far, and 'profile off' to disable it

    -- graceful shutdown now flags sockets that are busy to die so they die when
       they're done with their current connection

    -- sockets in persist_wait now get closed immediately during a graceful shutdown

    -- fix handling of OPTIONS responses; used to do its own state clearing but
       it now uses the next_request method as it should

    -- fix bug with determination of keep-alive in http 1.1 case specifying
       a connection: close header

    -- added 'uptime' management command to track how long Perlbal has been up

    -- new config commands: HEADER INSERT <svc> <header>: <value> and HEADER
       REMOVE <svc> <header> which will insert and remove headers from user
       requests before they're sent to backend proxy nodes.

    -- add dependency to Net::Netmask; now you can specify trusted_upstream_proxies
       on a service (SET service.trusted_upstream_proxies =, etc)
       which will allow requests from that range to set X-Forwarded-For, X-Host,
       and X-Forwarded-Host headers.

    -- fixed a bug that caused connections to hang when the backend responded
       before the user was done sending data

    -- reset some variables that weren't being reset: read_buf, read_ahead, read_size

    -- "proc" management command shows user and system CPU usage for Perlbal
       this run, as well as a delta since the last time you ran "proc"

    -- added Perlbal::XS interface for modules to use; also 'xs' management
       command to see the status of XS modules

    -- bug in PalImg caused crash on files with no length (or when another
       error occurs that causes no data to be sent to new_gif_palette function)

    -- ReproxyManager would sometimes let closed backends back into the pool
       and hand them off to clients, fixed to check for that

    -- new policy: you don't muck around with the internals of other classes.
       notably, clients don't change the internals of a backend and backends
       don't change the internals of a client.  this was causing all sorts of
       problems because nobody was cleaning up properly.  (especially with regard
       to "who is my backend's client" type questions.)

    -- fixed up code that did its own keep-alive checks to use the HTTPHeaders
       functions so that in the future every part of the code stays up to date

    -- Perlbal::Socket now has the option to keep track of all objects that
       are created.  new command to management interface 'leaks' will show
       all objects currently in memory.  turn this functionality on by enabling
       the TRACK_OBJECTS constant in Perlbal::Socket.

    -- split keep-alive logic into request and response methods and cleared
       up how that works

    -- rewrote reproxy URI support.  new class Perlbal::ReproxyManager does all
       of the work relating to reproxies.  it's basically a service class but
       stripped down and dealing with single endpoints instead of pools.  much
       much much more robust under heavy load.  (Junior, Brad)

    -- now that we support persistent connections, the 'queues' command didn't
       have an accurate time; added ClientProxy member last_request_time so
       we can accurately tell how long requests have been waiting for

    -- Danga::Socket got an overhaul; close and steal_socket now share a lot
       of code by calling _cleanup.  some more paranoia on making sure the
       object isn't already closed when we try to do things.

    -- lots more paranoia in close events and event_err handling for backends

    -- added tracking mode for helping look for leaked objects; records a
       backtrace of every object created.  "server track_obj = 0/1" to enable
       or disable it, and then "tracking" in a management interface to see.

    -- made Perlbal::objctor/objdtor take an object as their first parameter.
       much faster than using caller().

    -- fix Highpri plugin to not check hosts for high priority values when
       the host isn't defined

    -- made Palimg plugin far more paranoid about errors, and also uses new
       ClientHTTPBase scratch area for keeping track of data instead of using
       headers (which are generally slower)

    -- fixed bug in HTTPHeaders that set_version would inadvertently
       run into when used on a header created through new_response

    -- ClientProxy class now supports persistence; set persist_client on
       the proxy service in order to enable it.

    -- Palimg plugin now supports fallback to web server mode if the
       requested URI doesn't fit our desired pattern

    -- did some cleanup; made a bunch of HTTPHeaders accesses use the
       accessor methods instead of referencing into the object's private
       store of data

    -- fixed a crash caused by calling getsockname/getpeername on sockets
       that have been undefined after having been stolen during an internal
       redirect to another webserver

    -- fixed _simple_response to not return a body if we're serving
       to a HEAD request

    -- bug fix: don't send Not-Modified responses to requests for dynamic
       directory listings.  it was messing up persistent connections
       since the directory serving code didn't get passed down whether we
       were sending a body or not.  and not modifies on directories are hard:
       modify time isn't altogether useful.  (file sizes could change)

       this still does not-modifieds on indirect index.html directory
       requests, because _serve_request ends up eventually calling
       _serve_request on a different URI.  (brad)

    -- added BSD::Resource as dependency to Makefile.PL (brad)

    -- fixed 304 Not Modified responses to not send Content-Length
       and Content-Type headers.  (jr)

1.01 (2004-10-22)
    -- when internally redirecting a URL, perlbal advertises
       that it supports persisent HTTP connections now,
       and caches those sockets for 5 seconds.  (not configurable)
       useful under load, otherwise you waste all local ports
       on a machine

    -- ditch dependence on IO::SendFile.  do it ourselves (1 line)
       with perl's syscall function

    -- add doc/* and conf/* to MANIFEST file

    -- initial packaged release