ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Directory Server Enterprise Edition開発者ガイド
11g リリース1 (11.1.1.7.0)
B72440-01
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

7 プラグインを使用した内部操作の実行

この章では、対応するクライアント・リクエストが存在しない検索、変更、DN変更および削除の各操作を実行する方法について説明します。

この章で使用されるプラグインAPI関数の詳細は、第15章「Directory Server関数リファレンス(パートI)」を参照してください。

この章の内容は、次のとおりです。

7.1 内部操作の使用

この章では、内部検索、追加、変更、RDN変更および削除の各操作の使用方法について説明します。

7.1.1 内部操作を使用する場合

内部操作は、クライアントからの外部リクエストによってではなく、プラグインによって内部的に開始されるという意味で内部的です。内部操作コールは、プラグインで、クライアント・リクエストが存在しない操作をDirectory Serverfで実行する必要がある場合に使用します。

7.1.2 内部操作に関する問題

内部操作を使用する開発においては、パラメータ・ブロックを設定してすべてのメモリー管理を直接処理します。製品に付属のライブラリなどの、最適化されたバイナリを使用したデバッグ・セッションは、冗長になる場合があります。コードは慎重に確認してください。必要に応じて、見逃したエラーを指摘できるパートナと一緒に作業します。内部操作コール前後でのメモリー管理を誤ると、プラグインAPIでの他のコールよりも簡単に、理解が困難なセグメンテーション・フォルトが発生します。

また、内部操作の結果、一部のキャッシュのみが更新されます。たとえば、アクセス制御命令を変更すると、アクセス制御キャッシュが更新されます。CoSおよびロールで使用される属性への内部操作変更により、CoSおよびロールのキャッシュが更新されることはありません。

7.1.3 内部操作例の検索

この章で使用するプラグイン・コードは、install-path/examples/internal.cで見つかります。

7.2 内部操作例を使用する前に

サンプル・プラグインinternal.cを使用する前に、新しいサフィックスdc=example,dc=comを作成して、このサフィックスをサンプル・データに移入します。

7.2.1 サンプル・サフィックスを設定するには

実行済でない場合には、サフィックスdc=example,dc=comを使用して、サンプルのLDIFファイルinstall-path/resources/ldif/Example.ldifからロードされたデータを含むディレクトリ・インスタンスを設定します。

  1. 新規Directory Serverインスタンスを作成します。

    次に例を示します。

    $ dsadm create -h localhost -p 1389 /local/ds
    Choose the Directory Manager password:
    Confirm the Directory Manager password:
    $ 
    
  2. 新規Directory Serverインスタンスを開始します。

    次に例を示します。

    $ dsadm start /local/ds
    Server started: pid=4705
    $ 
    
  3. サフィックスdc=example,dc=comを作成します。

    たとえば、長い行は印刷ページに合わせて折り返します。

    $ dsconf create-suffix -h localhost -p 1389 dc=example,dc=com
    Enter "cn=directory manager" password: 
    Certificate "CN=defaultCert, CN=hostname:1636" presented by the
     server is not trusted.
    Type "Y" to accept, "y" to accept just once,
     "n" to refuse, "d" for more details: Y
    $ 
    
  4. サンプルLDIFをロードします。

    たとえば、長い行は印刷ページに合わせて折り返します。

    $ dsconf import -h localhost -p 1389 \
     install-path/resources/ldif/Example.ldif dc=example,dc=com
    Enter "cn=directory manager" password:  
    New data will override existing data of the suffix
     "dc=example,dc=com".
    Initialization will have to be performed on replicated suffixes. 
    Do you want to continue [y/n] ? y
    
    ## Index buffering enabled with bucket size 16
    ## Beginning import job...
    ## Processing file "install-path/resources/ldif/Example.ldif"
    ## Finished scanning file "install-path/resources/ldif/Example.ldif" (160 entries)
    ## Workers finished; cleaning up...
    ## Workers cleaned up.
    ## Cleaning up producer thread...
    ## Indexing complete.
    ## Starting numsubordinates attribute generation.
     This may take a while, please wait for further activity reports.
    ## Numsubordinates attribute generation complete. Flushing caches...
    ## Closing files...
    ## Import complete. Processed 160 entries in 5 seconds.
     (32.00 entries/sec)
    
    Task completed (slapd exit code: 0).
    $ 
    

関連項目

Directory Service Control Centerを使用して、このタスクを実行できます。

7.3 内部追加

内部追加の場合、パラメータ・ブロックに領域を割り当てます。slapi_add_entry_internal_set_pb ()を使用して、追加のためのパラメータ・ブロックを設定します。これにより、slapi_add_internal_pb()を起動したときに、エントリがパラメータ・ブロックに含まれます。その後、パラメータ・ブロックを解放します。内部追加では、パラメータ・ブロックによってサーバーに渡されるエントリが使用されます。

例7-1 内部追加操作(internal.c)

#include "slapi-plugin.h"

/* Internal operations require an ID for the plug-in.                   */
static Slapi_ComponentId * plugin_id     = NULL;

int
test_internal()
{
    Slapi_DN       * sdn;              /* DN holder for internal ops    */
    Slapi_Entry    * entry;            /* Entry holder for internal ops */
    Slapi_PBlock   * pb;               /* PBlock for internal ops       */
    char           * str = NULL;       /* String holder for internal ops*/
    int              len;              /* Length of LDIF from entry     */
    int              rc;               /* Return code; 0 means success. */

    /* Check that the example suffix exists.                            */
    sdn = slapi_sdn_new_dn_byval("dc=example,dc=com");
    if (slapi_be_exist(sdn)) {
        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,
            "test_internal in test-internal plug-in",
            "Suffix (%s) does not exist, exiting.\n",
            slapi_sdn_get_dn(sdn)
        );
        slapi_sdn_free(&sdn);
        return (0);
    }
    slapi_sdn_free(&sdn);

    /*
     * Add an entry for Quentin Cubbins to the example suffix
     * using slapi_add_entry_internal().                                */
    entry = slapi_entry_alloc();
    slapi_entry_set_dn(                /* slapi_entry_set_dn()          */
        entry,                         /* requires a copy of the DN.    */
        slapi_ch_strdup("uid=qcubbins,ou=People,dc=example,dc=com")
    );
                                       /* slapi_entry_add_string()      */
                                       /* does not require a copy.      */
    slapi_entry_add_string(entry, "objectclass", "top");
    slapi_entry_add_string(entry, "objectclass", "person");
    slapi_entry_add_string(entry, "objectclass", "organizationalPerson");
    slapi_entry_add_string(entry, "objectclass", "inetOrgPerson");
    slapi_entry_add_string(entry, "uid", "qcubbins");
    slapi_entry_add_string(entry, "givenName", "Quentin");
    slapi_entry_add_string(entry, "sn", "Cubbins");
    slapi_entry_add_string(entry, "cn", "Quentin Cubbins");
    slapi_entry_add_string(entry, "mail", "qcubbins@example.com");
    slapi_entry_add_string(entry, "userPassword", "qcubbins");
    slapi_entry_add_string(entry, "secretary",
        "uid=bjensen,ou=People,dc=example,dc=com");

    pb = slapi_pblock_new();           /* Make a new PBlock...          */
    rc = slapi_add_entry_internal_set_pb(
        pb,
        entry,
        NULL,                          /* No controls                   */
        plugin_id,
        SLAPI_OP_FLAG_NEVER_CHAIN      /* Never chain this operation.   */
    );
    if (rc != 0) {
        slapi_pblock_destroy(pb);
        return (-1);
    }

    str = slapi_entry2str(entry, &len);/* Entry as LDIF for the log.
                                        * Note you have to capture this
                                        * before the internal add, during
                                        * which the entry is consumed.  */
    rc = slapi_add_internal_pb(pb);    /* Entry consumed here           */
                                       /* ... get status ...            */
    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
    if (rc != LDAP_SUCCESS) {
        slapi_pblock_destroy(pb);
        return (-1);
    }

    slapi_pblock_destroy(pb);

    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,
        "test_internal in test-internal plug-in",
        "\nAdded entry:\n%sEntry length: %d\n", str, len
    );

    return (0);
}

内部操作には、plugin_idが必要であることに注意してください。示されているように、プラグインIDはグローバル変数です。プラグインIDは、この関数を使用してプラグインの初期化中に設定されます。

slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &plugin_id);

パラメータ・ブロックpbは、プラグイン初期化関数に渡されます。サンプル実装は、internal.cinternal_init()関数を参照してください。

7.4 内部変更

内部変更の場合、最初に、LDAPMod変更の配列を設定します。配列には、変更する属性タイプに関する情報が含まれます。変更には、属性値も含まれます。次に、内部追加の場合は、パラメータ・ブロックに領域を割り当てます。slapi_modify_internal_set_pb ()を使用して、パラメータ・ブロックを設定します。次に、slapi_modify_internal_pb ()を使用して変更操作を起動します。最後に、使用されたメモリーを解放します。

例7-2 内部変更操作(internal.c)

この例では、ユーザーの電子メール・アドレスの内部変更について説明します。

#include "slapi-plugin.h"

static Slapi_ComponentId * plugin_id     = NULL;

int
test_internal()
{
    Slapi_Entry    * entry;            /* Entry holder for internal ops */
    Slapi_PBlock   * pb;               /* PBlock for internal ops       */
    LDAPMod          mod_attr;         /* Attribute to modify           */
    LDAPMod        * mods[2];          /* Array of modifications        */
    char           * mail_vals[]  =    /* New mail address              */
                       {"quentin@example.com", NULL};
    int              rc;               /* Return code; 0 means success. */

    /* Modify Quentin's entry after his email address changes from
     * qcubbins@example.com to quentin@example.com.                     */
    mod_attr.mod_type   = "mail";
    mod_attr.mod_op     = LDAP_MOD_REPLACE;
    mod_attr.mod_values = mail_vals;   /* mail: quentin@example.com     */
    mods[0]             = &mod_attr;
    mods[1]             = NULL;

    pb = slapi_pblock_new();           /* Set up a PBlock...            */
    rc = slapi_modify_internal_set_pb(
        pb,
        "uid=qcubbins,ou=people,dc=example,dc=com",
        mods,
        NULL,                          /* No controls                   */
        NULL,                          /* DN rather than unique ID      */
        plugin_id,
        SLAPI_OP_FLAG_NEVER_CHAIN      /* Never chain this operation.   */
    );
    if (rc != 0) {
        slapi_pblock_destroy(pb);
        return (-1);
    }

    rc = slapi_modify_internal_pb(pb); /* Unlike internal add,          */
                                       /* nothing consumed here         */
                                       /* ... get status ...            */
    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
    if (rc != LDAP_SUCCESS) {
        slapi_pblock_destroy(pb);
        return (-1);
    }

    slapi_pblock_destroy(pb);          /* ... clean up the PBlock.      */

    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,
        "test_internal in test-internal plug-in",
        "\nModified attribute: %s\nNew value: %s\n",
        mod_attr.mod_type, mail_vals[0]
    );

    return (0);
}

mod_attrおよびmail_vals内のデータは、変更後も引き続き使用できます。内部追加とは異なり、内部変更では、パラメータ・ブロックに設定したデータは使用されません。

7.5 内部名前変更および移動(DN変更)

この項では、エントリの名前を変更したり、エントリを移動するプラグインの開発方法について説明します。

内部DN変更操作は、次のステージで実行されます。

  1. パラメータ・ブロックに領域を割り当てます。

  2. slapi_rename_internal_set_pb ()を使用して、操作を設定します。

  3. slapi_modrdn_internal_pb()を使用して、操作を起動します。

    操作の最初のステージはrenameです。操作の2番目のステージはmodrdnです。

  4. パラメータ・ブロックを解放します。

例7-3 内部名前変更または移動操作(internal.c)

この例では、内部DN変更操作について説明します。内部DN変更では、パラメータ・ブロックに設定したデータは使用されません。

#include "slapi-plugin.h"

static Slapi_ComponentId * plugin_id     = NULL;

int
test_internal()
{
    Slapi_PBlock   * pb;               /* PBlock for internal ops       */
    int              rc;               /* Return code; 0 means success. */

    pb = slapi_pblock_new();           /* Set up a PBlock again...      */
    rc = slapi_rename_internal_set_pb(
        pb,
        "uid=qcubbins,ou=people,dc=example,dc=com", /*Specify target entry*/
        "uid=fcubbins",                             /*Specify new RDN     */
        "ou=people,dc=example,dc=com",              /*Specify new superior*/
        /* The new superior is the same as the old superior.            */
        1,                             /* Delete old RDN                */
        NULL,                          /* No controls                   */
        NULL,                          /* DN rather than unique ID      */
        plugin_id,
        SLAPI_OP_FLAG_NEVER_CHAIN      /* Never chain this operation.   */
    );

    if (rc != LDAP_SUCCESS) {
        slapi_pblock_destroy(pb);
        return (-1);
    }

    rc = slapi_modrdn_internal_pb(pb); /* Like internal modify,         */
                                       /* nothing consumed here.        */
                                       /* ... get status ...            */
    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
    if (rc != LDAP_SUCCESS) {
        slapi_pblock_destroy(pb);
        return (-1);
    }

    slapi_pblock_destroy(pb);          /* ... cleaning up.              */

    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,
        "test_internal in test-internal plug-in",
        "\nNew entry RDN: %s\n", "uid=fcubbins"
    );

    return (0);
}

7.6 内部検索

内部検索の場合、コールバックを使用して、サーバーによる検出内容を取得します。コールバックを使用すると、外部リクエストによって開始される操作でクライアント・アプリケーションに戻される情報(LDAP結果コード、検出されたエントリおよび参照)を取得できます。

取得するコールバック・データを設定します。また、サーバーによってコールバックされる関数を作成します。

例7-4 検索コールバック(internal.c)

このコードは、サンプル・プラグインinternal.cでコールバックを使用して、検出される最初のエントリのLDIF表現を取得する方法を示しています。エントリは、slapi_entry2str()をコールバック関数として使用し、内部検索中に検出されます。

#include "slapi-plugin.h"

struct cb_data {                       /* Data returned from search     */
    char * e_str;                      /* Entry as LDIF                 */
    int    e_len;                      /* Length of LDIF                */
};

int
test_internal_entry_callback(Slapi_Entry * entry, void * callback_data)
{
    struct cb_data * data;
    int              len;

    /* This callback could do something more interesting with the
     * data such as build an array of entries returned by the search.
     * Here, simply log the result.                                     */
    data        = (struct cb_data *)callback_data;
    data->e_str = slapi_entry2str(entry, &len);
    data->e_len = len;
    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,
        "test_internal_entry_callback in test-internal plug-in",
        "\nFound entry: %sLength: %d\n", data->e_str, data->e_len
    );
    return (-1);                       /* Stop at the first entry.      */
}                                      /* To continue, return 0.        */

このコールバックは、最初のエントリが検出されると検索を停止します。プラグインでは、検索によって戻される複数のエントリを処理することが必要な場合があります。このため、プラグインの処理内容に応じて、データへの領域の割当て方法を考慮します。

コールバック・データおよび実装された関数を使用して、内部検索を処理する準備が整いました。最初に、パラメータ・ブロックおよびコールバック・データに領域を割り当て、slapi_search_internal_pb_set ()を使用してパラメータ・ブロックを設定します。次に、slapi_search_internal_pb()を使用して検索を起動し、また、slapi_search_internal_callback_pb()を使用してコールバックを設定します。終了したら、割り当てた領域を解放します。

例7-5 内部検索操作(internal.c)

#include "slapi-plugin.h"

static Slapi_ComponentId * plugin_id     = NULL;

int
test_internal()
{
    Slapi_PBlock   * pb;               /* PBlock for internal ops       */
    char           * srch_attrs[] =    /* Attr. to get during search    */
                       {LDAP_ALL_USER_ATTRS, NULL};
    struct cb_data   callback_data;    /* Data returned from search     */
    int              rc;               /* Return code; 0 means success. */

    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,
        "test_internal in test-internal plug-in",
        "\nSearching with base DN %s, filter %s...\n",
        "dc=example,dc=com", "(uid=fcubbins)"
    );

    pb = slapi_pblock_new();           /* Set up a PBlock...            */
    rc = slapi_search_internal_set_pb(
        pb,
        "dc=example,dc=com",           /* Base DN for search            */
        LDAP_SCOPE_SUBTREE,            /* Scope                         */
        "(uid=fcubbins)",              /* Filter                        */
        srch_attrs,                    /* Set to get all user attrs.    */
        0,                             /* Return attrs. and values      */
        NULL,                          /* No controls                   */
        NULL,                          /* DN rather than unique ID      */
        plugin_id,
        SLAPI_OP_FLAG_NEVER_CHAIN      /* Never chain this operation.   */
    );

    if (rc != LDAP_SUCCESS) {
        slapi_pblock_destroy(pb);
        return (-1);
    }

    /* Internal search puts results into the PBlock, but uses callbacks
     * to get at the data as it is turned up by the search. In this case,
     * what you want to get is the entry found by the search.           */
    rc  = slapi_search_internal_pb(pb);
    rc |= slapi_search_internal_callback_pb(
        pb,
        &callback_data,
        NULL,                          /* No result callback            */
        test_internal_entry_callback,
        NULL                           /* No referral callback          */
    );

                                       /* ... get status ...            */
    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
    if (rc != LDAP_SUCCESS) {
        slapi_pblock_destroy(pb);
        return -1;
    }
                                       /* Free the search results when
                                        * finished with them.           */
    slapi_free_search_results_internal(pb);
    slapi_pblock_destroy(pb);          /* ... done cleaning up.         */

    return (0);
}

ここで、callback_dataをローカルに割り当てて解放します。データを別のプラグイン関数に渡す場合は、異なる方法でメモリーを管理できます。

7.7 内部削除

内部削除の場合、パラメータ・ブロックに領域を割り当ててから、slapi_delete_internal_set_pb()を使用してパラメータ・ブロックを設定します。slapi_delete_internal_pb()を使用して削除を起動します。最後に、パラメータ・ブロックを解放します。

内部削除では、パラメータ・ブロックに設定したデータは使用されません。