Sun Java logo     Previous      Contents      Index      Next     

Sun logo
Sun Java(TM) System Directory Server 5 2004Q2 Plug-In Developer's Guide 

Chapter 3
Getting Started With Directory Server Plug-Ins

This chapter provides an introduction to creating Directory Server plug-ins and enabling the server to use them. It covers the mechanics of writing and compiling plug-ins, configuring your Directory Server to recognize and load plug-ins, and generating log entries. It begins with a minimal but complete plug-in example to give you an idea of how the pieces fit together.


Tip

You can find complete code examples including all code covered here under ServerRoot/plugins/slapd/slapi/examples/.

The location of ServerRoot depends on how Directory Server was installed. Refer to Table 3 for details.


If you maintain plug-ins developed for a 4.x release of Directory Server, refer to Chapter 2, "What’s New," for information about what has changed since that release.


An Example Plug-In

This section demonstrates a plug-in that logs a famous greeting. You may want to perform the steps outlined here to appreciate the concepts covered in this chapter.

Find the Code

On the host where the directory is installed, have a look in the ServerRoot/plugins/slapd/slapi/examples/ directory. The example code covered in this section is ServerRoot/plugins/slapd/slapi/examples/hello.c.

Review the Plug-In

Code Example 3-1 logs Hello, World! at Directory Server startup.

Code Example 3-1  Hello, World! Plug-In (hello.c

#include "slapi-plugin.h"

Slapi_PluginDesc desc = {

    "Hello, World",                    /* plug-in identifier      */

    "Sun Microsystems, Inc.",          /* vendor name             */

    "5.2",                             /* plug-in revision number */

    "My first plug-in"                 /* plug-in description     */

};

/* Log a greeting at server startup if info logging is on for plug-ins */

int

hello()

{

    slapi_log_info_ex(

        SLAPI_LOG_INFO_AREA_PLUGIN,    /* Log if info logging is  */

        SLAPI_LOG_INFO_LEVEL_DEFAULT,  /* set for plug-ins.       */

        SLAPI_LOG_NO_MSGID,            /* No client at startup    */

        SLAPI_LOG_NO_CONNID,           /* No conn.  at startup    */

        SLAPI_LOG_NO_OPID,             /* No op.    at startup    */

        "hello() in My first plug-in", /* Origin of this message  */

        "Hello, World!\n"              /* Informational message   */

    );

    return 0;

}

/* Register the plug-in with the server */

#ifdef _WIN32

__declspec(dllexport)

#endif

int

hello_init(Slapi_PBlock * pb)

{

    int rc = 0;                        /* 0 means success         */

    rc |= slapi_pblock_set(            /* Plug-in API version     */

        pb,

        SLAPI_PLUGIN_VERSION,

        SLAPI_PLUGIN_CURRENT_VERSION

    );

    rc |= slapi_pblock_set(            /* Plug-in description     */

        pb,

        SLAPI_PLUGIN_DESCRIPTION,

        (void *) &desc

    );

    rc |= slapi_pblock_set(            /* Startup function        */

        pb,

        SLAPI_PLUGIN_START_FN,

        (void *) hello

    );

    return rc;

}

To log the greeting, the plug-in includes a function to be called at Directory Server startup. The plug-in also includes an initialization function to register the plug-in description, supported API version, and startup function with Directory Server.

The startup function specifies the message is from a plug-in (SLAPI_LOG_INFO_AREA_PLUGIN) and that it should be logged when informational logging is activated (SLAPI_LOG_INFO_LEVEL_DEFAULT). For this log message no client connection information is available (SLAPI_LOG_NO_MSGID, SLAPI_LOG_NO_CONNID, SLAPI_LOG_NO_OPID), as Directory Server calls the function at startup before any clients have connected. The function specifies where the log message originates ("hello() in My first plug-in"). Finally, it provides the famous log message itself.

The initialization function is named hello_init(). This function modifies the parameter block, pb, with the function slapi_pblock_set() to register the plug-in API version supported, the plug-in description, and the functions offered to Directory Server by this plug-in. As required for all plug-in initialization functions, hello_init() returns 0 on success, -1 on failure. The function slapi_pblock_set() returns 0 if successful, -1 otherwise. It is therefore not necessary to set the return code to -1 explicitly in Code Example 3-1.

Build It

Build the plug-in as a shared object, libtest-plugin.so or libtest-plugin.sl, or dynamic link library, testplugin.dll, depending on your platform. For example, on Solaris platforms:

$ make

Use the Makefile in ServerRoot/plugins/slapd/slapi/examples/ to compile and link the code for a 32-bit Directory Server. This builds and links all plug-in examples into the same library. Refer to 64-Bit Plug-In Locations for details on building a plug-in when using a 64-bit Directory Server.

Plug It In

To get Directory Server to recognize our plug-in we add a configuration entry for the plug-in to the directory configuration.

Updating Directory Server Configuration

Start by copying the plug-in configuration entry in LDIF format in the comment at the top of hello.c to a separate file, hello.ldif, as shown in Code Example 3-2.

Code Example 3-2  Configuration Entry (hello.c

dn: cn=Hello World,cn=plugins,cn=config

objectClass: top

objectClass: nsSlapdPlugin

objectClass: extensibleObject

cn: Hello World

nsslapd-pluginPath: <ServerRoot>/plugins/slapd/slapi/examples/<LibName>

nsslapd-pluginInitfunc: hello_init

nsslapd-pluginType: object

nsslapd-pluginId: Hello, World

nsslapd-pluginEnabled: on

nsslapd-pluginVersion: 5.2

nsslapd-pluginVendor: Sun Microsystems, Inc.

nsslapd-pluginDescription: My first plug-in

Change the value of nsslapd-pluginPath to correspond to the absolute path to the plug-in library. Directory Server requires an absolute path, not a relative path.

Notice that nsslapd-pluginInitfunc identifies the plug-in initialization function.

With Directory Server running, add the plug-in configuration entry to the directory:

$ ldapmodify -a -p port -h host -D "cn=Directory Manager" -w password -f hello.ldif

With Directory Server still running, turn on logging for plug-in informational messages as shown in Code Example 3-3.

Code Example 3-3  Turning on Informational Logging for Plug-Ins 

$ ldapmodify -p port -h host -D "cn=Directory Manager" -w password

dn: cn=config

changetype: modify

replace: nsslapd-infolog-area

nsslapd-infolog-area: 65536

^D

65536 is equivalent to 0x10000, the value of SLAPI_LOG_INFO_AREA_PLUGIN defined in slapi-plugin.h. If your plug-in informational log messages use log level SLAPI_LOG_INFO_LEVEL_EXTRA instead of SLAPI_LOG_INFO_LEVEL_DEFAULT, you must also set the value of nsslapd-infolog-level on cn=config to a non-zero value such as 1 to view such messages in the log.

Restarting Directory Server

After changing the Directory Server configuration by adding the plug-in configuration entry to the directory and turning on logging for plug-in informational messages, you must restart Directory Server for the server to register the plug-in.

$ ServerRoot/slapd-serverID/restart-slapd

Checking the Log

Once Directory Server has started, search the error log, ServerRoot/slapd-serverID/logs/errors, for Hello, World! You should find an entry similar to:

[14/Jul/2112:12:44:19 +0200] - INFORMATION - hello() in My first plug-in - conn=-1 op=-1 msgId=-1 - Hello, World!

Finally, turn off informational logging (reset nsslapd-infolog-area to 0) for plug-in messages to avoid slowing down your Directory Server.


Writing Directory Server Plug-Ins

This section focuses on the basics of coding a Directory Server plug-in. It covers the key tasks of using the right header file to specify use of the plug-in API, including an initialization function called by Directory Server when registering plug-in functionality, setting parameter block values, and registering plug-in functions.

Include the Header File for the Plug-In API

In ServerRoot/plugins/slapd/slapi/include/slapi-plugin.h, the plug-in API is defined. Observe that the header file includes ldap.h, the entry point for the standard and extended LDAP C APIs, and includes ldap_msg.h, the list of error message identifiers used by Directory Server.

In general, interfaces exposed by Directory Server are specified under ServerRoot/plugins/slapd/slapi/include/. For details about specific features of the API, refer to the Directory Server Plug-In Developer’s Reference.

To use the API, include slapi-plugin.h in the declaration section of your plug-in source:

#include "slapi-plugin.h"

As a rule, use appropriate macros in your Makefile or project file to tell the linker to look for header files under ServerRoot/plugins/slapd/slapi/include/.

Write Your Plug-In Functions

Directory Server calls plug-in functions in the context of a Directory Server operation, when a bind, add, search, modify, or delete is performed, for example. You need not export these functions, as they become available in the appropriate scope when registered with Directory Server at startup. The main body of this guide covers writing such functions.

A plug-in function prototype looks similar to that of any other locally used function. Many plug-in functions are passed a parameter block. For example:

int prebind_auth(Slapi_PBlock * pb); /* External authentication. */

You may also use additional helper functions not registered with Directory Server. This guide does not cover additional helper functions, but some of the sample plug-ins delivered with the product include such functions.

Use Appropriate Return Codes

In general, return 0 from your plug-in functions when they complete successfully. For some functions that search for matches, 0 means a successful match, -1 means no match found. For pre-operation functions, 0 means Directory Server should continue processing the operation. When you want the server to stop processing the operation after your pre-operation function completes, return a positive value such as 1.

When plug-in functions do not complete successfully, send a result to the client if appropriate, log an error message, and return a non-zero value, such as the LDAP result code from ServerRoot/plugins/slapd/slapi/include/ldap-standard.h, for example.

Write an Initialization Function

All plug-ins must include an initialization function that registers the plug-in version compatibility, the plug-in description, plug-in functions, and any other data required by the plug-in. The initialization function takes a pointer to a Slapi_PBlock structure as a parameter. Refer to Code Example 3-1 for an example.

The initialization function returns 0 if everything registers successfully and -1 if registration fails for any configuration information or function. A return code of -1 from a plug-in initialization function prevents the server from starting.

Directory Server may call the initialization function more than once during startup.

Set Configuration Information Through the Parameter Block

Recall that Directory Server passes a parameter block pointer to the plug-in initialization function. This parameter block holds configuration information and may hold other data from Directory Server. It is the structure into which you add configuration information and pointers to plug-in functions using calls to slapi_pblock_set().


Tip

To read parameter values, use slapi_pblock_get(). To write parameter values, use slapi_pblock_set(). Use of other functions may crash the server.


Specifying Compatibility

Specifying compatibility with the plug-in API version as defined in slapi-plugin.h and described in the Directory Server Plug-In Developer’s Reference. If you are creating a new plug-in for example, use SLAPI_PLUGIN_CURRENT_VERSION or SLAPI_PLUGIN_VERSION_03. For example, to specify that a plug-in supports the current version, version 3, of the plug-in API:

slapi_pblock_set(pb,SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03);

Here, pb is the parameter block pointer passed to the initialization function, and SLAPI_PLUGIN_VERSION signifies you are setting plug-in API version compatibility in the parameter block.

Specifying the Plug-In Description

Specify the plug-in description in a Slapi_PluginDesc structure, as specified in slapi-plugin.h and described in the Directory Server Plug-In Developer’s Reference. Call slapi_pblock_set() to register the description:

slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION,(void *) &desc);

where desc is a Slapi_PluginDesc structure containing the plug-in description. Refer to Code Example 3-1 for an example.

Set Pointers to Functions Through the Parameter Block

Register plug-in functions according to what operation Directory Server is going to perform, is performing, or has just performed. In other words, Directory Server typically calls plug-in functions before, during, or after a standard operation.

Macros that specify when Directory Server should call plug-ins have the form SLAPI_PLUGIN_*_FN. As the sample plug-ins demonstrate, the macro used to register a plug-in function depends entirely on what the function is supposed to do. For example, to register a plug-in function foo() to be called at Directory Server startup:

slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *) foo);

Here, pb is the parameter block pointer passed to the initialization function, and SLAPI_PLUGIN_START_FN signifies Directory Server calls foo() at startup. Note foo() returns 0 on success.

Where to Find Examples

Find sample plug-ins under ServerRoot/plugins/slapd/slapi/examples/.


Building Directory Server Plug-Ins

This section details how to build plug-in binaries. It deals with compilation and linking requirements for Directory Server plug-ins.

Include the Header File for the Plug-In API

The compiler needs to be able to locate the header files such as slapi-plugin.h. Find header files under ServerRoot/plugins/slapd/slapi/include/.

Link the Plug-In as a Shared Object or Dynamic Link Library

Link plug-ins so the plug-in library is reentrant and portable and can be shared. Code Example 3-4 shows one way of building a plug-in library for use with a 64-bit Directory Server running on Solaris platforms.

Code Example 3-4  Makefile for a 64-Bit Solaris Sample Plug-In Library (Makefile64

INCLUDE_FLAGS = -I../include

CFLAGS = $(INCLUDE_FLAGS) -D_REENTRANT -KPIC -xarch=v9 -DUSE_64

LDFLAGS = -G

DIR64 = 64

OBJS = dns.o entries.o hello.o internal.o testpwdstore.o testsaslbind.o testextendedop.o testpreop.o testpostop.o testentry.o testbind.o testgetip.o

all: MKDIR64 $(DIR64)/libtest-plugin.so

MKDIR64:

    @if [ ! -d $(DIR64) ]; then mkdir $(DIR64); fi

$(DIR64)/libtest-plugin.so: $(OBJS)

    $(LD) $(LDFLAGS) -o $@ $(OBJS)

.c.o:

    $(CC) $(CFLAGS) -c $<

clean:

    -rm -f $(OBJS) libtest-plugin.so $(DIR64)/libtest-plugin.so

The CFLAGS -xarch=v9 and -DUSE_64 specify that the compiler build the library for use with a 64-bit server. Notice also that the 64-bit library is placed in a directory ending in 64/. An extra directory is required for 64-bit plug-ins, as a 64-bit server adds the name of the extra directory to the path name when searching for the library. Refer to 64-Bit Plug-In Locations for further information.

Code Example 3-5 shows 32-bit equivalent of the Makefile.

Code Example 3-5  Makefile for a 32-Bit Solaris Sample Plug-In Library (Makefile

INCLUDE_FLAGS = -I../include

CFLAGS = $(INCLUDE_FLAGS) -D_REENTRANT -KPIC

LDFLAGS = -G

OBJS = dns.o entries.o hello.o internal.o testpwdstore.o testsaslbind.o testextendedop.o testpreop.o testpostop.o testentry.o testbind.o testgetip.o

all: libtest-plugin.so

libtest-plugin.so: $(OBJS)

    $(LD) $(LDFLAGS) -o $@ $(OBJS)

.c.o:

    $(CC) $(CFLAGS) -c $<

clean:

    -rm -f $(OBJS) libtest-plugin.so

Notice that both 32-bit and 64-bit versions of the plug-in library may coexist on the same host.

Where to Find Examples

Build rules are in ServerRoot/plugins/slapd/slapi/examples/Makefile and in ServerRoot/plugins/slapd/slapi/examples/Makefile64. Refer to these files for the recommended setup for compilation and linking on your platform.


Plugging Libraries into Directory Server

This section covers server plug-in configuration and explains how to load plug-ins so Directory Server initializes them and registers the functionality they provide. It touches on specifying dependencies between Directory Server plug-ins.

Create a Configuration Entry for Your Plug-In

Plug-in configuration entries specify information Directory Server requires. It uses the information to load a plug-in at Directory Server startup, to identify the plug-in to Directory Server, and to pass parameters to the plug-in at load time.

Example Plug-In Configuration Entry

Directory Server can be configured to use an Attribute Value Uniqueness plug-in, whose configuration entry is shown in Code Example 3-6, to ensure unique attribute values across multiple master servers. This plug-in is part of the Sun Java System Directory Server Resource Kit.

Code Example 3-6  Sample Configuration Entry (Extracted From dse.ldif

dn: cn=Attribute Value Uniqueness,cn=plugins,cn=config

objectClass: top

objectClass: nsSlapdPlugin

objectClass: extensibleObject

cn: Attribute Value Uniqueness

nsslapd-pluginPath: ServerRoot/lib/valueunique-plugin.so

nsslapd-pluginInitfunc: valueunique_init

nsslapd-pluginType: preoperation

nsslapd-pluginEnabled: off

nsslapd-pluginarg0: attribute=cn

nsslapd-pluginarg1: suffix=dc=example,dc=com

nsslapd-pluginarg2: dcsleaf

nsslapd-plugin-depends-on-type: database

nsslapd-pluginId: UniqueValue

nsslapd-pluginVersion: 5.2

nsslapd-pluginVendor: Sun Microsystems, Inc.

nsslapd-pluginDescription: Unique attribute values across multiple servers

View entries like this in ServerRoot/slapd-serverID/config/dse.ldif and in the comments of examples under ServerRoot/plugins/slapd/slapi/examples/.

Configuration Entry Attributes

Edit your plug-in configuration entry as LDIF. To complete the configuration entry, you must include at minimum the information identified as required in Table 3-1.

Table 3-1  Configuration Entry Attributes 

Attribute

Description

Required/Optional

cn

Common name for the plug-in, corresponding to the name registered by the plug-in

Required

nsslapd-pluginEnabled

Status of your plug-in after Directory Server startup, either on or off

Required

nsslapd-pluginInitFunc

Name of the initialization function called during Directory Server startup as it appears in the plug-in code

Required

nsslapd-pluginPath

Full path to the library containing the plug-in, not including 64-bit directory for 64-bit plug-in libraries

Refer to 64-Bit Plug-In Locations for details.

Required

nsslapd-pluginType

Plug-in type that defines the types of functions the plug-in implements

Refer to Types and Dependencies for details.

Required

nsslapd-depends-on-named

One or more plug-in dependencies on plug-in names (RDN) such as State Change Plugin or Multimaster Replication Plugin

Refer to Types and Dependencies for details.

Optional

nsslapd-depends-on-type

One or more plug-in dependencies on plug-in types such as preoperation or database

Refer to Types and Dependencies for details.

Optional

nsslapd-pluginArg[0-9]+

A parameter passed to the plug-in at Directory Server startup such as suffix=dc=example,dc=com

Refer to Parameters Specified in the Configuration Entry for details.

Optional

nsslapd-pluginDescription

One-line description as specified in the spd_description field of the plug-in Slapi_PluginDesc structure

Optional

nsslapd-pluginId

Identifier as specified in the spd_id field of the plug-in Slapi_PluginDesc structure

Optional

nsslapd-pluginVendor

Vendor name as specified in the spd_vendor field of the plug-in Slapi_PluginDesc structure

Optional

nsslapd-pluginVersion

Version number as specified in the spd_version field of the plug-in Slapi_PluginDesc structure

Optional

The rest of this section covers types, dependencies, and parameters.

Types and Dependencies

The plug-in type tells Directory Server which type of plug-in functions may be registered by a plug-in. Plug-in types correspond to the principle type of operation a plug-in performs. Refer to Table 1-1 and Table 1-2 for short explanations of plug-in types. The Directory Server Plug-In Developer’s Reference also describes plug-in types. The Directory Server Plug-In Developer’s Reference lists nsslapd-pluginType attribute values corresponding to the type identifiers specified in slapi-plugin.h.

Determining plug-in type is straightforward when you know what the plug-in must do. For example, if you write a plug-in to handle authentication of a request before Directory Server processes the bind for that request, then the type is preoperation. In other words, the plug-in does something to the request prior to the bind operation. Such a plug-in therefore registers at least a pre-bind plug-in function to process the request prior to the bind. If, on the other hand, you write a plug-in to encode passwords and compare incoming passwords with encoded passwords, then the type is pwdstoragescheme. Such a plug-in registers at least password encoding and compare functions. In both cases, plug-in type follows plug-in function.

Plug-in dependencies tell Directory Server a plug-in requires one or more other plug-ins in order to function properly. Directory Server resolves dependencies as it loads plug-ins. Therefore, Directory Server fails to register a plug-in if a plug-in it depends on cannot be registered.

Specify plug-in dependencies by name, using nsslapd-depends-on-named, or by type, using nsslapd-depends-on-type. Here, plug-in name refers to the plug-in Relative Distinguished Name (RDN) from the configuration entry. Plug-in type is a type identifier from the list of types in the Directory Server Plug-In Developer’s Reference. Both nsslapd-depends-on-named and nsslapd-depends-on-type can take multiple values.

A plug-in configuration entry may specify either kind or both kinds of dependencies. Use the configuration entry to identify dependencies on specific plug-ins by name. Identify dependencies on a type of plug-ins by type. If a dependency identifies a plug-in by name, Directory Server only registers the plug-in after it manages to register the named plug-in. If a dependency identifies a plug-in by type, Directory Server only registers the plug-in after it manages to register all plug-ins of the specified type.

Do not confuse plug-in registration dependencies with a mechanism to specify the order in which Directory Server calls plug-ins. The order in which Directory Server calls plug-ins is not configurable.

Parameters Specified in the Configuration Entry

Your plug-in can retrieve parameters specified in the configuration entry attributes of the form nsslapd-pluginArg[0-9]+. If you include parameters in the configuration entry, then:

Use slapi_pblock_get() to retrieve the arguments as in Code Example 3-7 from ServerRoot/plugins/slapd/slapi/examples/testextendedop.c, where the configuration entry includes the following line:

nsslapd-pluginarg0: 1.2.3.4

Directory Server makes this argument, an OID, available to the plug-in through the parameter block passed to the plug-in initialization function.

Code Example 3-7  Configuration Entry with Arguments (testextendedop.c

#include "slapi-plugin.h"

Slapi_PluginDesc expdesc = {

    "test-extendedop",                 /* plug-in identifier       */

    "Sun Microsystems, Inc.",          /* vendor name              */

    "5.2",                             /* plug-in revision number  */

    "Sample extended operation plug-in"/* plug-in description      */

};

/* Register the plug-in with the server.                           */

#ifdef _WIN32

__declspec(dllexport)

#endif

int

testexop_init(Slapi_PBlock * pb)

{

    char ** argv;                      /* Args from configuration  */

    int     argc;                      /* entry for plug-in.       */

    char ** oid_list;                  /* OIDs supported           */

    int     rc = 0;                    /* 0 means success          */

    int     i;

    /* Get the arguments from the configuration entry.             */

    rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGV, &argv);

    rc |= slapi_pblock_get(pb, SLAPI_PLUGIN_ARGC, &argc);

    if (rc != 0) {

        slapi_log_info_ex(

            SLAPI_LOG_INFO_AREA_PLUGIN,

            SLAPI_LOG_INFO_LEVEL_DEFAULT,

            SLAPI_LOG_NO_MSGID,

            SLAPI_LOG_NO_CONNID,

            SLAPI_LOG_NO_OPID,

            "testexop_init in test-extendedop plug-in",

            "Could not get plug-in arguments.\n"

        );

        return (rc);

    }

    /* Extended operation plug-ins may handle a range of OIDs. */

    oid_list = (char **)slapi_ch_malloc((argc + 1) * sizeof(char *));

    for (i = 0; i < argc; ++i) {

        oid_list[i] = slapi_ch_strdup(argv[i]);

        slapi_log_info_ex(

            SLAPI_LOG_INFO_AREA_PLUGIN,

            SLAPI_LOG_INFO_LEVEL_DEFAULT,

            SLAPI_LOG_NO_MSGID,

            SLAPI_LOG_NO_CONNID,

            SLAPI_LOG_NO_OPID,

            "testexop_init in test-extendedop plug-in",

            "Registering plug-in for extended operation %s.\n",

            oid_list[i]

        );

    }

    oid_list[argc] = NULL;

    

    rc |= slapi_pblock_set(            /* Plug-in API version      */

        pb,

        SLAPI_PLUGIN_VERSION,

        SLAPI_PLUGIN_CURRENT_VERSION

    );

    rc |= slapi_pblock_set(            /* Plug-in description      */

        pb,

        SLAPI_PLUGIN_DESCRIPTION,

        (void *) &expdesc

    );

    rc |= slapi_pblock_set(            /* Extended op. handler     */

        pb,

        SLAPI_PLUGIN_EXT_OP_FN,

        (void *) test_extendedop

    );

    rc |= slapi_pblock_set(            /* List of OIDs handled     */

        pb,

        SLAPI_PLUGIN_EXT_OP_OIDLIST,

        oid_list

    );

    return (rc);

}

You can specify multiple parameters using multiple attributes, nsslapd-pluginArg0, nsslapd-pluginArg1, nsslapd-pluginArg2, and so forth.

64-Bit Plug-In Locations

Directory Server searches for plug-in libraries using the value of nsslapd-pluginPath in the plug-in configuration entry. 64-bit servers search for 64-bit libraries by adding a directory name to the end of the path name.

For example, if the value of nsslapd-pluginPath is set in the configuration entry as follows:

nsslapd-pluginPath: /myplugins/mylib.so

A 64-bit Directory Server running on Solaris platforms searches for a 64-bit plug-in library named:

/myplugins/64/mylib.so

A 32-bit Directory Server searches for 32-bit plug-in libraries using the exact path specified as the value of nsslapd-pluginPath. A 32-bit Directory Server using the same configuration entry would search for the plug-in library named:

/myplugins/mylib.so

Directory Server fails to start when it cannot find a plug-in library specified in the configuration entry.

Modify the Directory Server Configuration

With Directory Server running, add your plug-in configuration entry using the ldapmodify command:

$ ldapmodify -a -p port -h host -D "cn=Directory Manager" -w password -f file.ldif

Here, file.ldif contains the plug-in configuration entry. If everything works as expected, Directory Server adds your plug-in configuration entry to the Directory Server configuration (stored in ServerRoot/slapd-serverID/config/dse.ldif).

Restart Directory Server

Directory Server does not load plug-ins dynamically. Instead, you must restart the server. Directory Server then registers your plug-in at startup.

Set logging so Directory Server logs plug-in informational messages. Refer to Set Appropriate Log Level in the Directory Server Configuration for details. After setting the log level appropriately, you can have the server copy log messages to standard output:

$ ServerRoot/slapd-serverID/stop-slapd
$ ServerRoot/slapd-serverID/start-slapd -d 65536

When everything works fine, restart without the -d option or turn off plug-in log messages to avoid slowing down Directory Server. You can adjust logging levels through the Logs node under the Configuration tab of Directory Server Console, for example.


Logging Plug-In Messages

This section shows you how to generate messages in the Directory Server logs, how to set the log level such that Directory Server writes particular types of messages to the log, and then how to find the messages logged.

Three Levels of Message Severity

The plug-in API provides log functions for logging fatal error messages, warnings and information. Error messages and warnings are always logged. Logging of informational messages is turned off by default. Recall you can adjust log levels through the console or on the command line while Directory Server is running.


Tip

Error logging may slows down Directory Server, as Directory Server waits for the system to write each log message to disk.

Use logging when you need it. Turn it off when you do not.


Refer to the Directory Server Plug-In Developer’s Reference for details on each of the logging functions.

Fatal Errors

For fatal errors, use slapi_log_error_ex(). In many cases, you may return -1 after you log the message to indicate to Directory Server that a serious problem has occurred.

Code Example 3-8  Logging a Fatal Error Message 

#include "slapi-plugin.h"

#include "example-com-error-ids.h" /* example.com unique

                                      error IDs file       */

int

foobar(Slapi_PBlock * pb)

{

    char * error_cause;

    int    apocalypse = 1;         /* Expect the worst.    */

    /* ... */

    if (apocalypse) {              /* Server to crash soon */

        slapi_log_error_ex(

            EXCOM_SERVER_MORIBUND, /* Unique error ID      */

            SLAPI_LOG_NO_MSGID,

            SLAPI_LOG_NO_CONNID,

            SLAPI_LOG_NO_OPID,

            "example.com: foobar in baz plug-in",

            "cannot write to file system: %s\n",

            error_cause

        );

        return -1;

    }

    return 0;

}

In Code Example 3-8, foobar() logs an error as Directory Server is about to crash.


Tip

If the plug-ins are internationalized, use macros rather than literal strings for the last two arguments to slapi_log_*_ex() functions.


Warnings

For serious situations that require attention and involve messages that should always be logged, use slapi_log_warning_ex().

In Code Example 3-9, foobar() logs a warning because the disk is nearly full.

Code Example 3-9  Logging a Warning Message 

#include "slapi-plugin.h"

#include "example-com-warning-ids.h" /* example.com unique

                                        warning IDs file  */

int

foobar()

{

    int disk_use_percentage;

    /* ... */

    if (disk_use_percentage >= 95) {

        slapi_log_warning_ex(

            EXCOM_DISK_FULL_WARN,    /* unique warning ID */

            SLAPI_LOG_NO_MSGID,

            SLAPI_LOG_NO_CONNID,

            SLAPI_LOG_NO_OPID,

            "example.com: foobar in baz plug-in",

            "disk %.0f%% full, find more space\n",

            disk_use_percentage

        );

    }

    return 0;

}

Informational Messages

For purely informational or debug messages, use slapi_log_info_ex(). This function can be set for default logging, meaning the message is not logged when logging is turned off for plug-ins. It can also be set only when heavy logging is used, meaning the message is logged only when plug-in logging is on and the level is set to log all informational messages.

Refer to Code Example 3-1 for an example of how to log an informational message from a plug-in.

Set Appropriate Log Level in the Directory Server Configuration

Log levels may be set for plug-in informational messages, as for a number of other Directory Server subsystems. You can set the log level through the console. You can also set the log level from the command line, using the ldapmodify command to change the values of the nsslapd-infolog-area and nsslapd-infolog-level attributes on the configuration object, dn: cn=config. Refer to Updating Directory Server Configuration for an example.

Setting nsslapd-infolog-area to 65536 (the value of SLAPI_LOG_INFO_AREA_PLUGIN expressed as a decimal) turns on plug-in informational logging. Leaving nsslapd-infolog-level unspecified or setting it to 0 turns on information logging as specified using SLAPI_LOG_INFO_DEFAULT. Setting nsslapd-infolog-level a non-zero value turns on heavier informational logging, including messages registered with SLAPI_LOG_INFO_LEVEL_EXTRA.

Find Messages in the Log

The log file for errors, warnings, and informational messages is ServerRoot/slapd-serverID/logs/errors. All messages go to the same log so you can easily determine what happened in chronological order.

Messages consist of a timestamp, followed by an identifier, followed by the other information in the log message. For example:

[15/Jul/2112:12:44:10 +0200] - INFORMATION - Backend Database - conn=-1 op=-1 msgId=-1 - Checkpointing database ...

Use the identifiers to filter what you do not need.



Previous      Contents      Index      Next     


Copyright 2004 Sun Microsystems, Inc. All rights reserved.