+=head2 ERROR HANDLING
+
+To create a new error object, use C<< $self->make_error($type, $cb, %args) >>.
+This method will create a new C<Amanda::Changer::Error> object and optionally
+invoke a callback with it. If C<$type> is C<fatal>, then
+C<< $chg->{'fatal_error'} >> is made a reference to the new error object. The
+callback C<$cb> (which should be made using C<make_cb()> from
+C<Amanda::MainLoop>) is called with the new error object. The C<%args> are
+added to the new error object. In use, this looks something like:
+
+ if (!$success) {
+ return $self->make_error("failed", $params{'res_cb'},
+ reason => "notfound",
+ message => "Volume '$label' not found");
+ }
+
+This method can also be called as a class method, e.g., from a constructor.
+In this case, it returns the resulting error object, which should be fatal.
+
+ if (!$config_ok) {
+ return Amanda::Changer->make_error("fatal", undef,
+ message => "config error");
+ }
+
+For cases where a number of errors have occurred, it is helpful to make a
+"combined" error. The method C<make_combined_error> takes care of this
+operation, given a callback and an array of tuples C<[ $description, $err ]>
+for each error. This method uses some heuristics to figure out the
+appropriate type and reason for the combined error.
+
+ if ($left_err and $right_err) {
+ return $self->make_combined_error($params{'finished_cb'},
+ [ [ "from the left", $left_err ],
+ [ "from the right", $right_err ] ]);
+ }
+
+Any additional keyword arguments to C<make_combined_error> are put into the
+combined error; this is useful to set the C<slot> attribute.
+
+The method C<< $self->check_error($cb) >> is a useful method for subclasses to
+avoid doing anything after a fatal error. This method checks
+C<< $self->{'fatal_error'} >>. If the error is defined, the method calls C<$cb>
+and returns true. The usual recipe is
+
+ sub load {
+ my $self = shift;
+ my %params = @_;
+
+ return if $self->check_error($params{'res_cb'});
+ # ...
+ }
+
+=head2 CONFIG
+
+C<Amanda::Changer->new> calls subclass constructors with two parameters: a
+configuration object and a changer specification. The changer specification is
+the string that led to creation of this changer device. The configuration
+object is of type C<Amanda::Changer::Config>, and can be treated as a hashref
+with the following keys:
+
+ name -- name of the changer section (or "default")
+ is_global -- true if this changer is the default changer
+ tapedev -- tapedev parameter
+ tpchanger -- tpchanger parameter
+ changerdev -- changerdev parameter
+ changerfile -- changerfile parameter
+ properties -- all properties for this changer
+ device_properties -- device properties from this changer
+
+The four parameters are just as supplied by the user, either in the global
+config or in a changer section. Changer authors are cautioned not to try to
+override any of these parameters as previous changers have done (e.g.,
+C<changerfile> specifying both configuration and state files). Use properties
+instead.
+
+The C<properties> and C<device_properties> parameters are in the format
+provided by C<Amanda::Config>. If C<is_global> is true, then
+C<device_properties> will include any device properties specified globally, as
+well as properties culled from the global tapetype.
+
+The C<configure_device> method generally takes care of the intricacies of
+handling device properties. Pass it a newly opened device and it will apply
+the relevant properties, returning undef on success or an error message on
+failure.
+
+The C<get_property> method is a shortcut method to get the value of a changer
+property, ignoring its the priority and other attributes. In a list context,
+it returns all values for the property; in a scalar context, it returns the
+first value specified.
+
+Many properties are boolean, and Amanda has a habit of accepting a number of
+different ways of writing boolean values. The method
+C<< $config->get_boolean_property($prop, $default) >> will parse such a
+property, returning 0 or 1 if the property is specified, C<$default> if it is
+not specified, or C<undef> if the property cannot be parsed.
+
+=head2 PERSISTENT STATE AND LOCKING
+
+Many changer subclasses need to track state across invocations and between
+different processes, and to ensure that the state is read and written
+atomically. The C<with_locked_state> provides this functionality by
+locking a statefile, only unlocking it after any changes have been written back
+to it. Subclasses can use this method both for mutual exclusion (ensuring that
+only one changer operation is in progress at any time) and for atomic state
+storage.
+
+The C<with_locked_state> method works like C<synchronized> (in
+L<Amanda::MainLoop>), but with some extra arguments:
+
+ $self->with_locked_state($filename, $some_cb, sub {
+ # note: $some_cb shadows outer $some_cb; see Amanda::MainLoop::synchronized
+ my ($state, $some_cb) = @_;
+ # ... and eventually:
+ $some_cb->(...);
+ });
+
+The callback C<$some_cb> is assumed to take a changer error as its first
+argument, and if there are any errors locking the statefile, they will be
+reported directly to this callback. Otherwise, a wrapped version of
+C<$some_cb> is passed to the inner C<sub>. When this wrapper is invoked, the
+state will be written to disk and unlocked before the original callback is
+invoked.
+
+The state itself begins as an empty hashref, but subclasses can add arbitrary
+keys to the hash. Serialization is currently handled with L<Data::Dumper>.
+
+=head2 PARAMETER VALIDATION
+
+The C<validate_params> method is useful to make sure that the proper parameters
+are present for a particular method, dying if not. Call it like this:
+
+ $self->validate_params("load", \%params);
+
+The method currently only supports the "load" method, but can be expanded to
+cover other methods.
+
+=head1 SEE ALSO
+
+The Amanda Wiki (http://wiki.zmanda.com) has a higher-level description of the
+changer model implemented by this package.
+
+See amanda-changers(7) for user-level documentation of the changer implementations.