def setup_limits(conf_file, limits_file, do_reload=True,
                 dry_run=False, debug=False):
    """
    Set up or update limits in the Redis database.

    :param conf_file: Name of the configuration file, for connecting
                      to the Redis database.
    :param limits_file: Name of the XML file describing the limits to
                        configure.
    :param do_reload: Controls reloading behavior.  If True (the
                      default), a reload command is issued.  If False,
                      no reload command is issued.  String values
                      result in a reload command of the given load
                      type, and integer or float values result in a
                      reload command of type 'spread' with the given
                      spread interval.
    :param dry_run: If True, no changes are made to the database.
                    Implies debug=True.
    :param debug: If True, debugging messages are emitted while
                  loading the limits and updating the database.
    """

    # If dry_run is set, default debug to True
    if dry_run:
        debug = True

    # Connect to the database...
    conf = config.Config(conf_file=conf_file)
    db = conf.get_database()
    limits_key = conf['control'].get('limits_key', 'limits')
    control_channel = conf['control'].get('channel', 'control')

    # Parse the limits file
    limits_tree = etree.parse(limits_file)

    # Now, we parse the limits XML file
    lims = []
    for idx, lim in enumerate(limits_tree.getroot()):
        # Skip tags we don't recognize
        if lim.tag != 'limit':
            warnings.warn("Unrecognized tag %r in limits file at index %d" %
                          (lim.tag, idx))
            continue

        # Construct the limit and add it to the list of limits
        try:
            lims.append(parse_limit_node(db, idx, lim))
        except Exception as exc:
            warnings.warn("Couldn't understand limit at index %d: %s" %
                          (idx, exc))
            continue

    # Now that we have the limits, let's install them
    if debug:
        print >>sys.stderr, "Installing the following limits:"
        for lim in lims:
            print >>sys.stderr, "  %r" % lim
    if not dry_run:
        database.limit_update(db, limits_key, lims)

    # Were we requested to reload the limits?
    if do_reload is False:
        return

    # OK, figure out what kind of reload to do
    params = []
    if do_reload is True:
        # Nothing to do; use default semantics
        pass
    elif (isinstance(do_reload, (int, long, float)) or
          (isinstance(do_reload, basestring) and do_reload.isdigit())):
        params = ['spread', do_reload]
    else:
        params = [str(do_reload)]

    # Issue the reload command
    if debug:
        cmd = ['reload']
        cmd.extend(params)
        print >>sys.stderr, ("Issuing command: %s" %
                             ' '.join(str(c) for c in cmd))
    if not dry_run:
        database.command(db, control_channel, 'reload', *params)
Set up or update limits in the Redis database.

    :param conf_file: Name of the configuration file, for connecting
                      to the Redis database.
    :param limits_file: Name of the XML file describing the limits to
                        configure.
    :param do_reload: Controls reloading behavior.  If True (the
                      default), a reload command is issued.  If False,
                      no reload command is issued.  String values
                      result in a reload command of the given load
                      type, and integer or float values result in a
                      reload command of type 'spread' with the given
                      spread interval.
    :param dry_run: If True, no changes are made to the database.
                    Implies debug=True.
    :param debug: If True, debugging messages are emitted while
                  loading the limits and updating the database.