Perl Interface

From wiki.zmanda.com
Revision as of 19:44, 26 June 2008 by Dustin (talk | contribs) (add link to pod)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Starting with version 2.6.0, Amanda ships with a Perl interface to the core, and with an increasing proportion of the core itself written in Perl.

Modules

All Amanda modules have the prefix Amanda::. The specific modules correspond loosely to C modules of the same name; for example, the contents of device.h are available in Amanda::Device. The modules are not installed in Perl's default search path, but are located by default at $prefix/lib/amanda/perl.

All Amanda modules contain POD, plain old documentation, that is readable via the perldoc command, e.g.,

perldoc /usr/lib/amanda/perl/Amanda/Device.pm

In general, this POD describes the perl-specific calling conventions and other details of the module, while omitting the higher-level descsription that it shares with the C module. The latter description is available on this wiki.

POD (Documentation)

Documentation for all Amanda modules in the trunk (the latest development version) are available here.

Applications

Amanda applications written in Perl have a few features in common. They usually begin with

#! @PERL@
use lib '@amperldir@';

causing them to use the perl binary with which Amanda was configured, and to search the proper directory for Amanda modules.

The Amanda::Util module makes application setup fairly straightforward. Consult an existing Perl application for examples.

Features

Version

Amanda requires at least perl-5.6.0. Any features not available in that version are prohibited. Due to the impossibility of testing all version combinations, and the difficulty of installing, no CPAN-based or other third-party modules are permitted.

Integers

Perl's built-in handling of large integers is arguably worse than C's. Large integers are silently converted to doubles, which may result in loss of least-significant digits. Losing a few bytes of a multi-gigabyte dumpfile could be disastrous, so this situation must be avoided.

The solution we've selected is to convert all integers coming from C into Math::BigInt objects, Perl's built-in arbitrary-precision integers. While this has a nontrivial performance penalty, it avoids any chance of silent rounding.

On entry into C code, all Perl integers or Math::BigInt objects are range checked and converted to a C quantity of the appropriate bitlength.

Build Architecture

Source for the Amanda perl modules is stored in the top-level directory perl/. This directory contains server-specific, client-specific, and common modules; the Makefile figures out which modules should be built for a specific installation. Some Amanda modules are native Perl, while others are interfaces to C code, built with SWIG. Both kinds of modules are stored side-by-side in perl/Amanda/. Finally, perl/amglue/ contains macros, functions, and other material to support the build process.

Native Perl Modules

Native Perl modules usually need some substitutions from configure, and as such have the suffix .pm.in. They are specified in the Makefile.am with a stanza like this:

# PACKAGE: Amanda::Foo
Amanda_DATA += Amanda/Foo.pm
EXTRA_DIST += Amanda/Foo.pm.in
DISTCLEANFILES += Amanda/Foo.pm

SWIG Modules

SWIG modules are, of course, a bit more complicated. SWIG converts C/C++ header files to extension modules. In common usage, SWIG is applied directly to an existing header file, with precomplier macros and typemaps applied to tweak its behavior where necessary. The result is usually a scripting language interface that is awkward but functional, but no code duplication. We want the Amanda Perl interface to be as natural as possible, as it will eventually be the primary or only interface.

Amanda modules, then, are built from distinct files, with the suffix .swg. These are technically header files, with many SWIG declarations (preceded by %) included. Fully understanding them requires a hearty familiarity with SWIG, but adding a new constant or function should be fairly straightforward.

The Makefile.am stanza for a SWIG module is a bit longer:

# PACKAGE: Amanda::Foo
libFoodir = $(amperldir)/auto/Amanda/Foo
libFoo_LTLIBRARIES = libFoo.la
libFoo_la_SOURCES = Amanda/Foo.c $(AMGLUE_SWG)
libFoo_la_LDFLAGS = $(PERL_EXT_LDFLAGS)
libFoo_la_LIBADD = libamglue.la \
        $(top_builddir)/common-src/libamanda.la
Amanda_DATA += Amanda/Foo.pm
EXTRA_DIST += Amanda/Foo.swg Amanda/Foo.pm
MAINTAINERCLEANFILES += Amanda/Foo.c Amanda/Foo.pm

The notable variable in this stanza is libFoo_la_LIBADD, which lists any libraries on which this library will depend.

There are a few helpful macro families defined in amglue/amglue.swg:

Exports

All Amanda modules use the Exporter module to export their symbols. Symbols are available for import individually, or organized by theme into tags. For example, Amanda::Debug exports initialization symbols like dbopen under the tag :init, and logging functions like info under the tag :logging.

A few SWIG macros exist to make this easier; see the comments in perl/amglue/exports.swg for details.

Constants

Amanda has many, many constants, most of which are either enumerations (e.g., protocol states) or bitfields (e.g., access permissions). These are written as follows:

amglue_add_flag_tag_fns(running_as_flags);
amglue_add_constant(RUNNING_AS_ROOT, running_as_flags);
amglue_add_constant(RUNNING_AS_DUMPUSER, running_as_flags);
/* ... */

This creates a Perl export tag named :running_as_flags, all of the constants as scalars (e.g., $RUNNING_AS_ROOT). It also creates a Perl function running_as_flags_to_strings which converts an integer to a list of the names of all matching constants. This function is useful for displaying flag values without writing out bit-level operations in Perl.

Likewise, enumerations begin with amglue_add_enum_tag_fns(..):

amglue_add_enum_tag_fns(logtype_t);
amglue_add_constant(L_BOGUS, logtype_t);
amglue_add_constant(L_FATAL, logtype_t);
/* ... */

and define a function logtype_t_to_string (note the singular) to convert an integer to the single corresponding string.

The macro amglue_add_constant_short is like amglue_add_constant, but uses a shorter name for conversion to string form. We could write, e.g.,

amglue_add_constant_short(RUNNING_AS_DUMPUSER, DUMPUSER, running_as_flags);

amglue_add_constant_noshort is like amglue_add_constant, but will never use the symbol when converting to string form. This is used for bit combinations, enumeration maxima, etc.

Integers

perl/amglue/integers.swg installs the requisite typemaps to accomplish the integer conversions described above. For cases where the typemaps will not apply automatically (such as other typemaps), use the following functions to convert integers:

  • Perl-to-C conversion functions are named amglue_SvXN, where X is U (unsigned) or I (signed) and N is the bitlength (8, 16, 32, or 64).
  • The C-to-Perl conversion functions are amglue_newSVu64 and amglue_newSVi64 for unsigned and signed integers, respectively. These functions take advantage of C's automatic integer upcasting to accept any size integer.

Amglue

The C source in the perl/amglue directory is built into libamglue, a shared library providing common support functionality for perl modules. This includes the integer handling code, and any other functions which are needed in more than one module.

History

Please consult the [email protected] archives for the "why" and "why perl" discussions.