Skip Navigation Links | |
Exit Print View | |
Oracle Directory Server Enterprise Edition Developer's Guide 11 g Release 1 (11.1.1.5.0) |
Part I Directory Server Plug-In API Guide
1. Before You Start Writing Plug-Ins
2. Changes to the Plug-In API Since Directory Server 5.2
3. Getting Started With Directory Server Plug-Ins
4. Working With Entries Using Plug-Ins
5. Extending Client Request Handling Using Plug-Ins
6. Handling Authentication Using Plug-Ins
7. Performing Internal Operations With Plug-Ins
8. Writing Entry Store and Entry Fetch Plug-Ins
9. Writing Extended Operation Plug-Ins
10. Writing Matching Rule Plug-Ins
How Matching Rule Plug-Ins Work
What a Matching Rule Plug-In Does
Configuring Matching Rule Plug-Ins
Registering Matching Rule Plug-Ins
Handling Extensible Match Filters
How Directory Server Handles Extensible Match Searches
Thread Safety and Filter Matching Functions
Input Parameters for Filter Index Functions
Output Parameters for Filter Index Functions
Thread Safety and Filter Index Functions
Input Parameters for Filter Factory Functions
Output Parameters for Filter Factory Functions
Thread Safety and Filter Factory Functions
Filter Object Destructor Function
Indexing Entries According to a Matching Rule
How Directory Server Handles the Index
Input Parameters for Indexer Factory Functions
Output Parameters for Indexer Factory Functions
Enabling Sorting According to a Matching Rule
How Directory Server Performs Sorting According to a Matching Rule
Handling an Unknown Matching Rule
Internal List of Correspondences
11. Writing Password Storage Scheme Plug-Ins
12. Writing Password Quality Check Plug-Ins
13. Writing Computed Attribute Plug-Ins
Part II Directory Server Plug-In API Reference
14. Data Type and Structure Reference
15. Function Reference, Part I
16. Function Reference, Part II
This section covers how to provide plug-in support for a directory index that is based on a matching rule. Matching rule plug-ins are not required to enable indexing for the matching rules the plug-ins support.
Note - Directory Server can use your plug-in for extensible match searches even if you provide no indexing capability.
Without support for indexing, however, Directory Server must generate search results from the entire directory, which severely impacts search performance.
Directory indexes speed up client searches. Directory Server can build a list of search result entries by looking through the index rather than the entire directory. When directories contain many entries, indexes offer a considerable search performance boost. Directory administrators therefore configure the directory to maintain indexes for attributes that are searched regularly.
To maintain an index for a custom matching rule supported by your plug-in, the server requires an indexer function. The indexer function is capable of translating attribute values to index keys. Directory Server calls the indexer function to create the index, and subsequently when adding, modifying, or deleting attribute values, because such changes can affect the index.
To read an index for a custom matching rule, Directory Server requires a filter index function. The filter factory function provides a pointer to this function. Refer to Handling Extensible Match Filters and Filter Index Function for details.
Directory Server relies on the indexer factory function in your plug-in to set up an indexing object and provide a pointer to the appropriate indexer function.
The following figure shows how Directory Server performs indexing based on a matching rule.
Figure 10-4 Directory Server Maintaining an Index Using a Matching Rule
The following summarizes the process shown in Figure 10-4.
Directory Server creates a parameter block, setting parameters to indicate the matching rule OID and attribute type to match. Directory Server then calls the indexer factory function.
The indexer factory function examines the parameter block and allocates an indexer object if necessary. The function also sets pointers to the indexer and filter index functions. If necessary, the function sets a pointer to a destructor to free the indexer object before returning control to Directory Server.
Directory Server sets the parameter block to indicate attribute values to translate to keys and calls the indexer function.
The indexer function translates values to keys. After the indexer returns, Directory Server uses the keys to update the index.
Directory Server frees the parameter block. If necessary, the server frees the indexer object by using the destructor provided.
Be aware that Directory Server can call indexer factory functions concurrently. Indexer factory functions must therefore be thread safe.
The main filter functions are as follows:
An indexer function takes a parameter block from Directory Server that contains a pointer to a berval array of attribute values. The function then generates a berval array of corresponding keys from the values. Finally, the function sets a pointer in the parameter block to the keys.
The following figure shows how Directory Server uses the indexer function.
Figure 10-5 Indexer Function Context
The following example shows the indexer function for the case exact matching rule where the keys are the same as the values.
Example 10-7 Indexer Function (matchingrule.c)
#include "slapi-plugin.h" typedef struct plg_filter_t /* For manipulating filter obj. */ { char * f_type; /* Attribute type to match */ int f_op; /* Type of comparison * (<, <=, ==, >=, >, substr) * for the filter. */ struct berval ** f_values; /* Array of values to match */ } plg_filter_t; static int plg_index_entry(Slapi_PBlock * pb) { int rc = LDAP_OPERATIONS_ERROR; void * obj = NULL; /* Server lets the plug-in */ plg_filter_t * fobj; /* handle the object type. */ struct berval ** values; /* Values from server */ if (slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &obj) == 0) { fobj = (plg_filter_t *)obj; if ( (slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUES, &values) == 0) && (values != NULL) ) { /* The case exact match builds the index keys * from the values by copying the values because * the keys and values are the same. * * Your matching rule may do something quite * different before setting the keys associated * with the values in the parameter block. */ rc = slapi_pblock_set( /* Set keys based on values. */ pb, SLAPI_PLUGIN_MR_KEYS, slapi_ch_bvecdup(values) ); } } return rc; }
Here, obj points to the indexer object, and values points to the berval array of attribute values. Notice that the function returns LDAP_OPERATIONS_ERROR on failure. Technically, LDAP_OPERATIONS_ERROR indicates bad sequencing of LDAP operations. For historical reasons, the error is used in this context to indicate an internal error.
An indexer function can get values for the following from the parameter block:
SLAPI_PLUGIN_MR_VALUES
SLAPI_PLUGIN_MR_OBJECT
An indexer function should generate the berval array of keys. The function should set SLAPI_PLUGIN_MR_KEYS in the parameter block before returning control to Directory Server. Refer to Part II, Directory Server Plug-In API Reference for details.
Directory Server never calls an indexer for the same indexer object concurrently. Directory Server can, however, call the function concurrently for different indexer objects. If you use global variables, ensure that your function handles such variables safely.
The indexer factory function takes a parameter block from Directory Server. The function sets parameters such that Directory Server can update an index or sort results based on a matching rule.
The following figure shows how Directory Server uses the indexer factory function.
Figure 10-6 Indexer Factory Function Context
The following example shows the indexer factory function for the case exact matching rule.
Example 10-8 Indexer Factory Function (matchingrule.c)
#include "slapi-plugin.h" #define PLG_OID "1.3.6.1.4.1.42.2.27.999.4.1" #define SUBSYS "CaseExactMatching Plugin" /* Functions to obtain connection information for logging. */ static long mypblock_get_msgid( Slapi_PBlock * pb); static int mypblock_get_connid(Slapi_PBlock * pb); static int mypblock_get_opid( Slapi_PBlock * pb); static int plg_indexer_create(Slapi_PBlock * pb) { int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* Init failed*/ char * mr_oid = NULL; /* MR OID from the server */ if (slapi_pblock_get(pb, SLAPI_PLUGIN_MR_OID, mr_oid) || (mr_oid == NULL)) { slapi_log_error_ex( -1, /* errorId */ mypblock_get_msgid(pb), mypblock_get_connid(pb), mypblock_get_opid(pb), SUBSYS, SLAPI_INTERNAL_ERROR, "plg_indexer_create failed: NULL OID values are invalid.\n" ); } else if (strcmp(mr_oid, PLG_OID) == 0) { if ( /* The MR OID from the server is handled by this plug-in. */ (slapi_pblock_set( /* This is for completeness. */ pb, /* Your plug-in may set a */ SLAPI_PLUGIN_MR_OID, /* different OID than the one */ PLG_OID /* provided by the server. */ ) == 0) && (slapi_pblock_set( /* Provide an appropriate */ pb, /* indexer function pointer. */ SLAPI_PLUGIN_MR_INDEX_FN, (void *)plg_index_entry ) == 0) && (slapi_pblock_set( /* Set the object destructor. */ pb, SLAPI_PLUGIN_DESTROY_FN, (void *)plg_filter_destroy ) == 0)) { rc = LDAP_SUCCESS; } else { slapi_log_error_ex( -1, /* errorId */ mypblock_get_msgid(pb), mypblock_get_connid(pb), mypblock_get_opid(pb), SUBSYS, SLAPI_INTERNAL_ERROR, "plg_indexer_create failed %d \n", rc ); } } return rc; }
Here, PLG_OID is the object identifier for the matching rule. plg_index_entry() is the indexer. plg_filter_destroy() is the destructor. Notice that the function returns LDAP_UNAVAILABLE_CRITICAL_EXTENSION on failure.
An indexer factory function can read the values for the following from the parameter block:
SLAPI_PLUGIN_MR_OID
SLAPI_PLUGIN_MR_TYPE
SLAPI_PLUGIN_MR_USAGE, indicates whether results must be sorted
SLAPI_PLUGIN_PRIVATE, if your plug-in uses private data that you specify in the plug-in initialization function
An indexer factory function should set values for at least the following in the parameter block before returning control to Directory Server:
SLAPI_PLUGIN_DESTROY_FN, a pointer to the indexer object destructor
SLAPI_PLUGIN_MR_INDEX_FN, a pointer to the indexer
SLAPI_PLUGIN_OBJECT, a pointer to the indexer object
Refer to Chapter 17, Parameter Block Reference for details about the parameter block.
This function must be thread safe. Directory Server can call this function concurrently.
An indexer object destructor function frees memory that was allocated for an indexer object set up by the indexer factory function. Directory Server calls the destructor after an index operation completes.
Indexer object destructors take a parameter block as their only argument, as do filter object destructors. The parameter block holds a pointer to the object in SLAPI_PLUGIN_OBJECT. Refer to the Filter Object Destructor Function for details.
Directory Server never calls a destructor for the same object concurrently.