Oracle NoSQL Database表Cドライバ・クイック・スタート

法律上の注意点

Copyright © 2011, 2012, 2013, 2014, 2015 Oracle and/or its affiliatesAll rights reserved.

このソフトウェアおよび関連ドキュメントの使用と開示は、ライセンス契約の制約条件に従うものとし、知的財産に関する法律により保護されています。ライセンス契約で明示的に許諾されている場合もしくは法律によって認められている場合を除き、形式、手段に関係なく、いかなる部分も使用、複写、複製、翻訳、放送、修正、ライセンス供与、送信、配布、発表、実行、公開または表示することはできません。このソフトウェアのリバース・エンジニアリング、逆アセンブル、逆コンパイルは互換性のために法律によって規定されている場合を除き、禁止されています。

ここに記載された情報は予告なしに変更される場合がありますまた、誤りが無いことの保証はいたしかねます。誤りを見つけた場合は、オラクル社までご連絡ください。

このソフトウェアまたは関連ドキュメントが、米国政府機関もしくは米国政府機関に代わってこのソフトウェアまたは関連ドキュメントをライセンスされた者に提供される場合は、次のNoticeが適用されます。

U.S. GOVERNMENT END USERS: Oracle programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, delivered to U.S. Government end users are "commercial computer software" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations.As such, use, duplication, disclosure, modification, and adaptation of the programs, including any operating system, integrated software, any programs installed on the hardware, and/or documentation, shall be subject to license terms and license restrictions applicable to the programs.No other rights are granted to the U.S. Government.

このソフトウェアまたはハードウェアは様々な情報管理アプリケーションでの一般的な使用のために開発されたものです。このソフトウェアまたはハードウェアは、危険が伴うアプリケーション(人的傷害を発生させる可能性があるアプリケーションを含む)への用途を目的として開発されていません。このソフトウェアまたはハードウェアを危険が伴うアプリケーションで使用する際、このソフトウェアまたはハードウェアを安全に使用するために、適切な安全装置、バックアップ、冗長性(redundancy)、その他の対策を講じることは使用者の責任となります。このソフトウェアまたはハードウェアを危険が伴うアプリケーションで使用したことに起因して損害が発生しても、オラクル社およびその関連会社は一切の責任を負いかねます。

OracleおよびJavaはOracle およびその関連企業の登録商標です。その他の名称は、他社の商標の可能性があります。

Intel、Intel Xeonは、Intel Corporationの商標または登録商標です。すべてのSPARCの商標はライセンスをもとに使用し、SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMDロゴ、AMD Opteronロゴは、Advanced Micro Devices, Inc.の商標または登録商標です。UNIXは、The Open Groupの登録商標です。

このソフトウェアまたはハードウェアおよびドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。

5/26/2015


目次

はじめに
インストール
プロキシ・サーバーの使用方法
Cクライアントのコンパイルと実行
ストアへの接続
プロキシ・サーバーの自動的な起動
表および索引定義の作成
表の行への書込み
表の行の削除
単一の表の行の読取り
複数の表の行の読取り
索引を使用した読取り
実行の順序付け
一貫性保証の設定
永続性保証の設定
プロキシ・サーバー・リファレンス
Oracle NoSQL Databaseプロキシ・サーバーの保護
プロキシ・サーバーのトラブル・シューティング

はじめに

この記事では、Oracle NoSQL Database Cドライバの概要について説明します。このドライバは、ネイティブCクライアントがOracle NoSQL Database表に格納されているデータにアクセスできるようにします。(Oracle NoSQL Databaseデータへのアクセス用のキー/値APIを提供するC JNIドライバがあります。そのドライバはJNIレイヤーに依存し、この記事では説明しません。)

Cドライバは、Oracle NoSQL Databaseサーバー・パッケージとは別のダウンロードとして入手できます。サーバーとドライバ両方のダウンロード・パッケージは次の場所から入手できます。

http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html

Cドライバが動作するためには、CクライアントとOracle NoSQL Databaseストア間でネットワーク・アクティビティを変換するプロキシ・サーバーを使用する必要があります。プロキシはJavaで記述され、Cクライアント・コードとOracle NoSQL Databaseストアの両方からネットワーク・アクセスが可能な任意のマシン上で実行できます。ただし、パフォーマンスとセキュリティ上の理由から、プロキシはドライバと同じローカル・ホスト上で実行し、プロキシをドライバと1:1構成で使用することをお薦めします(つまり、プロキシの各インスタンスを単一ドライバ・インスタンスとともに使用する必要があります)。

このクイック・スタートでは、Oracle NoSQL Database表APIスタート・ガイドで説明している概念を読み、理解していることを想定します。このガイドは、Oracle NoSQL Databaseサーバー・インストール・パッケージまたは次の場所にあります。

Cドライバで使用されるAPI全体については、C APIリファレンス・ガイドで説明しています。このドキュメントには、ブラウザで.../kv-c-driver-X.Y.Z/c/doc/html/index.htmlを参照することでCドライバ・パッケージでアクセスできます。

インストール

Cドライバとプロキシは、どちらも共通ダウンロード・パッケージで入手できます。プロキシ・サーバーはkvproxyディレクトリにあり、Java jarファイル(kvproxy.jar)として提供されています。プロキシを使用するには、Oracle NoSQL Databaseサーバー・インストールも必要です。具体的には、インストールのkvclient.jarファイルがプロキシで使用可能である必要があります。

Cドライバ・ライブラリは、クライアント・コードで使用する前にコンパイルする必要があります。このライブラリのソース・コードは、ドライバ・パッケージのcディレクトリで入手できます。ライブラリの依存関係とコンパイル手順は、cディレクトリにあるBUILDING.htmlで参照できます。

Cドライバはプリコンパイル済バイナリとしても入手できます。このバイナリにアクセスするには、関連するrpmまたはdebファイルをダウンロードしてインストールします。rpmまたはdebを使用すると、必要なJava jarファイルもシステムにインストールされます。このケースでは、関連するライブラリおよびjarファイルが/usr/local/libにインストールされます。これらを使用するには、このディレクトリを含むようにCLASSPATHおよびLD_LIBRARY_PATH環境変数を調整する必要があります。

プロキシ・サーバーの使用方法

プロキシ・サーバーは、表C APIからのネットワーク・トラフィックを受け入れ、Oracle NoSQL Databaseストアが理解できるリクエストに変換してから、変換したリクエストをストアに転送するJavaアプリケーションです。プロキシは、ストアのレスポンスを解釈し、それらをクライアントに転送する逆変換サービスも提供します。

プロキシ・サーバーは、ネットワーク・アクセス可能な任意のマシンで実行できます。リソース要件は最小限で、多くの場合、クライアント・ノードが実行されているのと同じマシンで実行できます。

Cクライアントがストアにアクセスするには、プロキシ・サーバーが実行されている必要があります。java -cpコマンド・ライン・オプションを使用するかCLASSPATH環境変数を使用することで、クラス・パスに次のjarファイルが設定されている必要があります。

  • KVHOME/lib/kvclient.jar

  • .../kv-c-driver-X.Y.Z/kvproxy/lib/kvproxy.jar

注意

rpmまたはdebを使用してインストールした場合、これらのファイルは/usr/local/libに配置されます。

プロキシ・サーバー自体は、oracle.kv.proxy.KVProxyコマンドを使用して起動します。少なくとも、プロキシ・サーバーの起動時には次の情報が必要です。

  • -helper-hosts

    これは、プロキシ・サーバーがストアへの接続に使用できるOracle NoSQL Databaseストレージ・ノードを表す1つ以上のホスト:ポート・ペアのリストです。

  • -port

    クライアント・コードがプロキシ・サーバーのこのインスタンスに接続できるポート。

  • -store

    プロキシ・サーバーが接続するストアの名前。

他の一連のコマンド・ライン・オプションを使用できます。特に、安全なストアでプロキシ・サーバーを使用している場合は、プロキシ・サーバーに認証情報を提供する必要があります。また、プロキシ・サーバーにストア名を識別することが必要になる可能性があります。プロキシ・サーバーとそのコマンド・ライン・オプションの詳細な説明は、プロキシ・サーバー・リファレンスを参照してください。

このクイック・スタート・ガイドで提供している単純な例は、デフォルト値で起動されたkvliteインスタンスに接続しているプロキシ・サーバーで動作するように作成されています。kvclient.jarおよびkvproxy.jarファイルの場所は、CLASSPATH環境変数を使用して提供されています。プロキシ・サーバーの起動に使用したコマンド・ライン・コールは次のとおりです。

nohup java oracle.kv.proxy.KVProxy -port 7010 \
-helper-hosts localhost:5000 -store kvstore

Cクライアントのコンパイルと実行

Cクライアントをコンパイルするには、libkvstore.soまたはlibkvstore-static.aをリンクします。これらは、cmakeに提供したインストール場所に含まれるlibディレクトリにあります。

.soファイルを使用する場合は、実行時にライブラリが見つかるように、LD_LIBRARY_PATH環境変数にインストール・ディレクトリを追加してください。

kvstore.hヘッダー・ファイルは、cmakeに提供したインストール場所に含まれるincludeディレクトリにあります。

ストアへの接続

ストア操作を実行するには、クライアント・コードとストア間にネットワーク接続を確立する必要があります。提供する必要のある2つの情報があります。

  1. kv_config_t構造を使用して、ストアの名前、ホストおよびポートを識別します。この構造に提供するホストとポートは、ストア内のノードをホストする任意のマシンです。(ストアは多くのホストから構成されるため、複数のホスト/ポートのペアから選択する必要があります。)

    kv_config_t構造体を作成するにはkv_create_config()を使用します。構造体はkv_release_config()を使用して解放できます。

  2. プロキシが実行されているホストとポートを識別します。これは、kv_open_store()を使用して行います。この関数は、後続のすべてのストア操作に使用するkv_store_t構造体を作成します。この構造体は、kv_close_store()を使用して解放します。

たとえば、"MyNoSQLStore"という名前のOracle NoSQL Databaseストアがあり、そのノードがn1.example.orgのポート5000で実行されているとします。さらに、ポート7010を使用してローカルホストでプロキシを実行しているとします。さらに、次の方法でストアへの接続をオープンおよびクローズします。

#include <stdlib.h>
#include <stdio.h>
#include "kvstore.h"

void open_store(kv_store_t **);
void do_store_ops(kv_store_t *);

int main(void) {
    kv_store_t *store = NULL;

    open_store(&store);
    if (!store) {
        goto ERROR;
    }

    do_store_ops(store);


ERROR:
    /* Close the store handle. */
    if (store) {
        kv_close_store(&store);
    }
    return 0;
}

void do_store_ops(kv_store_t *store)
{
    printf("Do store operations here.\n");
}

void
open_store(kv_store_t **store)
{
    kv_config_t *config = NULL;
    kv_error_t ret;

    ret = kv_create_config("kvstore",   // store name
                           "localhost", // host name
                           5000,        // host port
                           &config);

    if (ret != KV_SUCCESS) {
        return;
    }

    /* Connect to a proxy server */
    ret = kv_open_store(store, "localhost", 7010, config);
    if (ret != KV_SUCCESS) {
        printf("could not connect to the store.\n");
        // Release the configuration structure
        kv_release_config(&config);
    }
} 

安全なストアを使用している場合、ストア・ハンドルの構成にはユーザー名も含まれている必要があります。この目的にはkv_config_set_auth_user()を使用します。

プロキシ・サーバーの自動的な起動

クライアント・コードは、kv_open_store_with_proxy()を使用してストアを開く際にローカル・ホストでプロキシ・サーバーを起動できます。この関数では、kv_open_store()に必要なすべてのものに加え、kvclient.jarおよびkvproxy.jarファイルのディスク上の場所に移入されたkv_proxy_config_t構造体が必要です。

kv_proxy_config_t構造体は、kv_create_proxy_config()を使用して移入します。この構造体は、kv_release_proxy_config()を使用して解放できます(ストアを開くときにエラーが発生する場合にのみ必要です)。コードがプロキシ・サーバーで完了したら、kv_shutdown_proxy()を使用してシャット・ダウンします。

例:

int main(void) {
    kv_store_t *store = NULL;

    open_store(&store);
    if (!store) {
        goto ERROR;
    }

    do_store_ops(store);


ERROR:
    /* Close the store handle. */
    if (store) {
        kv_shutdown_proxy(store);
        kv_close_store(&store);
    }
    return 0;
}

// do_store_ops() not implemented in this example

void
open_store(kv_store_t **store)
{
    kv_config_t *config = NULL;
    kv_proxy_config_t *proxy_config = NULL;
    kv_error_t ret;

    const char *path2kvclient = "/export/kvstore/lib/kvclient.jar";
    const char *path2kvproxy = 
                        "/export/c_driver/kvproxy/lib/kvproxy.jar";

    ret = kv_create_config("kvstore",   // store name
                           "localhost", // host name
                           5000,        // host port
                           &config);
            // All configs are correct for kvlite
    if (ret != KV_SUCCESS) {
        return;
    }

    // Create the proxy configuration structure.
    // This must identify where the two relevant jar
    // files reside on disk.
    ret = kv_create_proxy_config(path2kvclient,
                                 path2kvproxy,
                                 &proxy_config);
    if (ret != KV_SUCCESS) {
        printf("could not create proxy config.\n");
        return;
    }

    ret = kv_open_store_with_proxy(store,
                                   "localhost",
                                   7010,
                                   config,
                                   proxy_config);
    if (ret != KV_SUCCESS) {
        printf("could not connect to the store.\n");
        // Release the configuration structure
        if (config) {
            kv_release_config(&config);
        }

        if (proxy_config) {
            kv_release_proxy_config(&proxy_config);
        }
        store = NULL;
    }
} 

表および索引定義の作成

ストアの表にデータを書き込む前に、表DDL文を使用して表を定義する必要があります。DDL文を使用して索引を定義することもできます。表DDLは、Oracle NoSQL Database表APIスタート・ガイドで詳細に説明されています。

表DDL文をCクライアント・コードからストアに送信する場合は、kv_table_execute_sync()またはkv_table_execute()を使用します。後者の関数はDDL文をストアに非同期で送信します。索引の作成または表の削除操作には長時間かかることがあるため、これらの操作時には非同期での送信が必要になることがあります。

たとえば、表を同期的に作成するには、次のようにします。

void do_store_ops(kv_store_t *store)
{
    kv_error_t ret;

    /* ... Data operations ... */
    kv_statement_result_t *result = NULL;

    const char *statement = "CREATE TABLE Users2 (\
        id INTEGER CHECK(id > 300), \
        firstName STRING, \
        lastName STRING, \
        description STRING, \
        PRIMARY KEY (SHARD(id, firstName), lastName)\
    )";

    ret = kv_table_execute_sync(store, statement, &result);
    if (ret != KV_SUCCESS) {
        printf("Table creation failed.\n");
        printf("Error message is %s\n", 
            kv_statement_result_get_error_message(result));
    } else {
        printf("Table create succeeded.\n");
    }   
} 

表の行への書込み

ストアに表を定義した後で、kv_create_row()を使用して空の表の行を作成します。次に、適切なkv_row_put_xxx()関数(xxxは書き込んでいるフィールドのデータ型)を使用して各フィールドにデータを移入します。最後に、kv_table_put()を使用して、表の行を実際にストアに書き込みます。たとえば、次のように表が設計されているとします。

"CREATE TABLE myTable (item STRING, \
                       description STRING, \
                       count INTEGER, \
                       percentage FLOAT, \
                       PRIMARY KEY (item))" 

表の行は次の形式で記述できます(簡潔にするために、ストアを開く操作と閉じる操作はスキップしています)。

void 
do_store_ops(kv_store_t *store)
{
    kv_error_t ret;
    kv_row_t *row = NULL;

    row = kv_create_row();
    if (!row) {
       printf("row creation failed.\n");
       goto cleanup;
    }

    ret = kv_row_put_string(row, "item", "Bolts");
    if (ret != KV_SUCCESS) {
        printf("row put 'item' failed.\n");
        goto cleanup;
    }
    ret = kv_row_put_string(row, "description", 
                            "Hex head, stainless");
    if (ret != KV_SUCCESS) {
        printf("row put 'description' failed.\n");
        goto cleanup;
    }
    ret = kv_row_put_int(row, "count", 5);
    if (ret != KV_SUCCESS) {
        printf("row put 'count' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_float(row, "percentage", 0.2173913);
    if (ret != KV_SUCCESS) {
        printf("row put 'percentage' failed.\n");
        goto cleanup;
    }

    ret = kv_table_put(store, "myTable", row,
                        NULL); // new version 
    if (ret != KV_SUCCESS) {
        printf("Store put failed.\n");
        goto cleanup;
    } else {
        printf("Store put succeeded.\n");
    }

cleanup:
    if (row) {
        kv_release_row(&row);
    }
} 

オプションやバージョン情報などを提供できる他のバージョンのkv_table_put()が存在します。詳細は、API Cのドキュメントを参照してください。

表の行の削除

表の行を削除するにはkv_table_delete()を使用します。この関数はKV_ERROR_Tを返さずに、整数を返します。

void
do_store_ops(kv_store_t *store)
{
    kv_error_t ret;
    kv_row_t *key = NULL;

    key = kv_create_row();
    if (!key) {
       printf("key creation failed.\n");
       goto cleanup;
    }

    ret = kv_row_put_string(key, "item", "Bolts");
    if (ret != KV_SUCCESS) {
        printf("row put 'item' failed.\n");
        goto cleanup;
    }

    ret = kv_table_delete(store, "myTable", key);
    // ret is 1 if a row was deleted
    //        0 if no row with the provided key was found
    //        < 0 if an error occurred. 
    if (ret < 0) {
        printf("Row deletion failed. %i\n", ret);
        goto cleanup;
    } else {
        printf("Row deletion succeeded.\n");
    }

cleanup:
    if (key) {
        kv_release_row(&key);
    }
} 

オプションやバージョン情報などを提供できる他のバージョンのkv_table_delete()が存在します。詳細は、API Cのドキュメントを参照してください。

単一の表の行の読取り

単一の表の行を読み取るには、取得する行に含まれるフィールド名とフィールド値が設定されたkv_row_t構造体を作成します。次に、取得された行の保持に使用する2つ目のkv_row_t構造体を作成します。行はkv_table_get()を使用して取得されます。適切なバージョンのkv_row_get_xxxx()を使用して、取得した行の各種フィールドを検証できます。xxxxは、検証しているフィールドのデータ型です。

たとえば、「表の行への書込み」で作成した表の行を取得するには、次のようにします。

void
do_store_ops(kv_store_t *store)
{
    kv_error_t ret;
    kv_row_t *key = NULL;

    key = kv_create_row();
    if (!key) {
       printf("key creation failed.\n");
       goto cleanup;
    }

    ret = kv_row_put_string(key, "item", "Bolts");
    if (ret != KV_SUCCESS) {
        printf("row put 'item' failed.\n");
        goto cleanup;
    }

    kv_row_t *retRow = NULL;
    retRow = kv_create_row();
    if (!retRow) {
       printf("retRow creation failed.\n");
       goto cleanup;
    }
    ret = kv_table_get(store, "myTable", key, &retRow);
    if (!retRow) {
        printf("Row retrieval failed.\n");
        goto cleanup;
    }

    const char *retItem = NULL, *retDescription = NULL;
    int retCount = 0;
    float retPercentage = 0.0;

    kv_row_get_string(retRow, "item", &retItem);
    kv_row_get_string(retRow, "description", &retDescription);
    kv_row_get_int(retRow, "count", &retCount);
    kv_row_get_float(retRow, "percentage", &retPercentage);

    printf("Item: %s. Desc: %s. Count is %i. Percent is %f\n",          
            retItem, retDescription, retCount, retPercentage);

cleanup:
    if (key) {
        kv_release_row(&key);
    } 

    if (retRow) {
        kv_release_row(&retRow);
    }
} 

複数の表の行の読取り

表から一度に複数行を読み取るにはkv_table_multi_get()またはkv_table_iterator()を使用します。これらの関数には、参照キーとして機能するkv_row_t構造体を提供する必要があります。提供するキーには、使用する関数に応じて異なる制限が適用されます。ここに示す例では、提供するキーに少なくともすべての表のshardキーが含まれていることを必要とするkv_table_multi_get()を使用します。存在しないshardキーがある場合、関数はエラーを返しませんが結果も返しません。

kv_table_multi_get()は、kv_iterator_next()を使用して繰り返すkv_iterator_t構造体を移入します。結果セット内の各部分で使用可能な行を取得するにはkv_iterator_get_result()およびkv_result_get_row()を使用します。

たとえば、次のような表を設計するとします。

CREATE TABLE myTable (
    itemType STRING,
    itemCategory STRING,
    itemClass STRING,
    itemColor STRING,
    itemSize STRING,
    price FLOAT,
    inventoryCount INTEGER,
    PRIMARY KEY (SHARD(itemType, itemCategory, itemClass), itemColor,
    itemSize)
) 

また、これに次のようなデータを移入します。

int main(void) {
    kv_store_t *store = NULL;

    open_store(&store);
    if (!store) {
        goto ERROR;
    }

    do_store_ops(store, "Hats", "baseball", "longbill",
                 "red", "small", 12.07, 127);

    do_store_ops(store, "Hats", "baseball", "longbill",
                 "red", "medium", 13.07, 201);

    do_store_ops(store, "Hats", "baseball", "longbill",
                 "red", "large", 14.07, 309);

    retrieve_table_rows(store);

ERROR:
    /* Close the store handle. */
    if (store) {
        kv_close_store(&store);
    }
    return 0;
}

void
do_store_ops(kv_store_t *store,
             const char *itemType, const char *itemCategory,
             const char *itemClass, const char *itemColor,
             const char *itemSize, float price, int inventoryCount)
{
    kv_error_t ret;
    kv_row_t *row = NULL;

    row = kv_create_row();
    if (!row) {
       printf("row creation failed.\n");
       goto cleanup;
    }

    ret = kv_row_put_string(row, "itemType", itemType);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemType' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "itemCategory", itemCategory);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemCategory' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "itemClass", itemClass);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemClass' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "itemColor", itemColor);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemColor' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "itemSize", itemSize);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemSize' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_float(row, "price", price);
    if (ret != KV_SUCCESS) {
        printf("row put 'price' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_int(row, "inventoryCount", inventoryCount);
    if (ret != KV_SUCCESS) {
        printf("row put 'inventoryCount' failed.\n");
        goto cleanup;
    }

    ret = kv_table_put(store, "myTable", row,
                        NULL); // new version 
    if (ret != KV_SUCCESS) {
        printf("Store put failed.\n");
        goto cleanup;
    } else {
        printf("Store put succeeded.\n");
    }

cleanup:
    if (row) {
        kv_release_row(&row);
    }
} 

その後、この例ではshardキーは表のすべての行に対して同一であるため、shardキーのみを提供するだけで表のすべての行を取得できます。(通常、表のすべての行を表示する場合は、keyパラメータに空の行を指定したkv_table_iteratorを使用します。)

 void
retrieve_table_rows(kv_store_t *store)
{
    kv_error_t ret;
    kv_iterator_t *iter = NULL;
    kv_row_t *key = NULL;

    key = kv_create_row();
    if (!key) {
       printf("key creation failed.\n");
       goto cleanup;
    }

    ret = kv_row_put_string(key, "itemType", "Hats");
    if (ret != KV_SUCCESS) {
        printf("row put 'itemType' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(key, "itemCategory", "baseball");
    if (ret != KV_SUCCESS) {
        printf("row put 'itemCategory' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(key, "itemClass", "longbill");
    if (ret != KV_SUCCESS) {
        printf("row put 'itemClass' failed.\n");
        goto cleanup;
    }

    ret = kv_table_multi_get(store,
                             "myTable",
                             key,
                             KV_FALSE /* Keyonly*/,
                             NULL /* Field range */,
                             NULL /* Included tables */,
                             NULL /* Read options */,
                             &iter);

    int nRows = 0;
    while (kv_iterator_next(iter) == KV_SUCCESS) {
        const kv_result_t *result;
        kv_row_t *retRow;
        const char *itemType = NULL;
        const char *itemCategory = NULL;
        const char *itemClass = NULL;
        const char *itemColor = NULL;
        const char *itemSize = NULL;
        float price = 0.0;
        int inventoryCount = 0;

        result = kv_iterator_get_result(iter);
        retRow = kv_result_get_row(result);

        nRows++;

        kv_row_get_string(retRow, "itemType", &itemType);
        kv_row_get_string(retRow, "itemCategory", &itemCategory);
        kv_row_get_string(retRow, "itemClass", &itemClass);
        kv_row_get_string(retRow, "itemSize", &itemSize);
        kv_row_get_string(retRow, "itemColor", &itemColor);
        kv_row_get_float(retRow, "price", &price);
        kv_row_get_int(retRow, "inventoryCount", &inventoryCount);

        printf("Row %d:\n", nRows);
        printf("\t%s, %s, %s:\n", itemType, itemCategory, itemClass);
        printf("\t\tColor: %s    itemSize: %s\n", itemColor, 
                itemSize);
        printf("\t\tprice: %f    inventory: %d\n", price, 
                inventoryCount);
    }

cleanup:
    if (key) {
        kv_release_row(&key);
    }

    if (iter) {
        kv_release_iterator(&iter);
    }
} 

索引を使用した読取り

kv_index_iterator()を使用して、指定した索引に基づいて表の行を読み取ります。この関数を使用するには、まずCREATE INDEX文を使用して索引を作成する必要があります。

結果セットのベースにする索引値を識別する方法は2つあります。最初の方法は、取得した索引付きフィールドと値を表すkv_row_t構造体を提供することです。2つ目の方法は、返される索引の開始値と終了値を識別するkv_field_range_t構造体を提供することです。kv_field_range_t構造体とkv_row_t構造体を一緒に使用して、戻りセット値を制限できます。

kv_row_tkv_field_range_tの両方の値がNULLの場合、指定した索引と一致する表のすべての行が戻りセットに含まれます。

たとえば、次のように定義された表があるとします。

CREATE TABLE myTable ( 
    surname STRING, 
    familiarName STRING, 
    userID STRING, 
    phonenumber STRING, 
    address STRING, 
    email STRING, 
    dateOfBirth STRING, 
    PRIMARY KEY (SHARD(surname, familiarName), userID)) 

索引は次のとおりです。

CREATE INDEX DoB ON myTable (dateOfBirth)

また、次のようなデータを表に移入します。

int main(void) {
    kv_store_t *store = NULL;

    open_store(&store);
    if (!store) {
        goto ERROR;
    }


    do_store_ops(store, "Anderson", "Pete", "panderson",
                 "555-555-5555", "1122 Somewhere Court",
                 "panderson@example.com", "1994-05-01");

    do_store_ops(store, "Andrews", "Veronica", "vandrews",
                 "666-666-6666", "5522 Nowhere Court",
                 "vandrews@example.com", "1973-08-21");

    do_store_ops(store, "Bates", "Pat", "pbates",
                 "777-777-7777", "12 Overhere Lane",
                 "pbates@example.com", "1988-02-20");

    do_store_ops(store, "Macar", "Tarik", "tmacar",
                 "888-888-8888", "100 Overthere Street",
                 "tmacar@example.com", "1990-05-17");

    read_index(store);


ERROR:
    /* Close the store handle. */
    if (store) {
        kv_close_store(&store);
    }
    return 0;
} 

void
do_store_ops(kv_store_t *store,
             const char *surname, const char *familiarName,
             const char *userID, const char *phone,
             const char *address, const char *email,
             const char *birthdate)
{
    kv_error_t ret;
    kv_row_t *row = NULL;

    row = kv_create_row();
    if (!row) {
       printf("row creation failed.\n");
       goto cleanup;
    }

    ret = kv_row_put_string(row, "surname", surname);
    if (ret != KV_SUCCESS) {
        printf("row put 'surname' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "familiarName", familiarName);
    if (ret != KV_SUCCESS) {
        printf("row put 'familiarName' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "userID", userID);
    if (ret != KV_SUCCESS) {
        printf("row put 'userID' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "phonenumber", phone);
    if (ret != KV_SUCCESS) {
        printf("row put 'phonenumber' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "address", address);
    if (ret != KV_SUCCESS) {
        printf("row put 'address' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "email", email);
    if (ret != KV_SUCCESS) {
        printf("row put 'email' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_string(row, "dateOfBirth", birthdate);
    if (ret != KV_SUCCESS) {
        printf("row put 'birthdate' failed.\n");
        goto cleanup;
    }



    ret = kv_table_put(store, "myTable", row,
                        NULL); // new version 
    if (ret != KV_SUCCESS) {
        printf("Store put failed.\n");
        goto cleanup;
    } else {
        printf("Store put succeeded.\n");
    }

cleanup:
    if (row) {
        kv_release_row(&row);
    }
} 

さらに、次の関数を使用し、DoB索引を使用して読み取ることができます。次の例では、BLOCK 1 (コード内のコメントを参照)は、BLOCK 2とともに使用すると結果セットが空になるためコメント・アウトされています。表全体を出力するにはBLOCK 1BLOCK 2の両方をコメントにします。

void
read_index(kv_store_t *store)
{
    kv_error_t ret;
    kv_iterator_t *iter = NULL;
    kv_row_t *key = NULL;
    kv_field_range_t *rangep = NULL;

    key = kv_create_row();
    if (!key) {
       printf("key creation failed.\n");
       goto cleanup;
    }

    // BLOCK 1:
    // Uncomment this block to look up only table rows with a 
    // dateOfBirth field set to "1988-02-20". If this
    // block and BLOCK 2 are both used, then the result set 
    // will be empty.
    //
    //ret = kv_row_put_string(key, "dateOfBirth", "1988-02-20");
    //if (ret != KV_SUCCESS) {
    //    printf("row put 'dateOfBirth' failed.\n");
    //    goto cleanup;
    //}

    // BLOCK 2:
    // This field range restricts the results set to only
    // those rows with a dateOfBirth field value between
    // "1990-01-01" and "2000-01-01", inclusive. 
    ret = kv_create_field_range("dateOfBirth", // Field
                                "1990-01-01",  // Start value 
                                KV_TRUE,       // Inclusive?
                                "2000-01-01",  // End value
                                KV_TRUE,       // Inclusive? 
                                &rangep);
    if (ret != KV_SUCCESS) {
        printf("field range creation failed.\n");
        goto cleanup;
    }

    ret = kv_index_iterator(store, "myTable", "DoB",
                            key, // Key to use for the lookup
                            KV_FALSE, // Whether only primary keys 
                                      // are returned
                            rangep, // Field range
                            NULL,  // Included tables
                            KV_DIRECTION_UNORDERED,
                            NULL,  // Read options 
                            0, // max iterator results, 0 - use default
                            &iter);
    int nRows = 0;
    while (kv_iterator_next(iter) == KV_SUCCESS) {
        const kv_result_t *result;
        kv_row_t *retRow;
        const char *surname = NULL;
        const char *familiarName = NULL; 
        const char *userID = NULL;   
        const char *phonenumber = NULL;
        const char *address = NULL;
        const char *email = NULL;
        const char *dateOfBirth = NULL;

        result = kv_iterator_get_result(iter);
        retRow = kv_result_get_row(result);

        nRows++;

        kv_row_get_string(retRow, "surname", &surname);
        kv_row_get_string(retRow, "familiarName", &familiarName);
        kv_row_get_string(retRow, "userID", &userID);
        kv_row_get_string(retRow, "phonenumber", &phonenumber);
        kv_row_get_string(retRow, "address", &address);
        kv_row_get_string(retRow, "email", &email);
        kv_row_get_string(retRow, "dateOfBirth", &dateOfBirth);

        printf("Row %d:\n", nRows);
        printf("\t%s, %s (%s):\n", familiarName, surname, userID);
        printf("\t\tPhone: %s\n", phonenumber);
        printf("\t\tEmail: %s\n", email);
        printf("\t\tAddress: %s\n", address);
        printf("\t\tDoB: %s\n", dateOfBirth);
    }

cleanup:
    if (key) {
        kv_release_row(&key);
    }

    if (rangep) {
        kv_release_field_range(&rangep);
    }

    if (iter) {
        kv_release_iterator(&iter);
    }
} 

実行の順序付け

書込み操作の順序を保持するkv_operations_t構造体を作成するにはkv_create_operations()を使用します。すべての書込み操作は、すべての操作が同じshardキーを共有するかぎり、単一の原子的構造体として実行されます。

一連の1つ以上のkv_create_table_xxxx_op()関数を使用して、操作をkv_operations_t構造体に移入します。xxxxは、操作リストに挿入する操作のタイプを示します。たとえば、kv_create_table_delete_op()は行の削除操作を順序に挿入します。

操作の順序付けはkv_table_execute_operations()を使用して実行されます。

たとえば、「複数の表の行の読取り」で説明されているようなデータが移入されている表がある場合は、表の各行の価格および在庫値を次のような原子的操作で更新できます。

int main(void) {
    kv_error_t ret;
    kv_store_t *store = NULL;
    kv_operations_t *op = NULL;
    kv_operation_results_t *resultp = NULL;

    open_store(&store);
    if (!store) {
        goto ERROR;
    }


    op = kv_create_operations();

    // Causes all rows to be released when op is released.
    kv_operations_set_donate(op);

    ret = add_op_list(op, "Hats", "baseball", "longbill",
                 "red", "small", 13.07, 107);
    if (ret != KV_SUCCESS) {
        printf("adding to op list failed.\n");
        return -1;
    } 

    ret = add_op_list(op, "Hats", "baseball", "longbill",
                 "red", "medium", 14.07, 198);
    if (ret != KV_SUCCESS) {
        printf("adding to op list failed.\n");
        return -1;
    }

    ret = add_op_list(op, "Hats", "baseball", "longbill",
                 "red", "large", 15.07, 140);
    if (ret != KV_SUCCESS) {
        printf("adding to op list failed.\n");
        return -1;
    }

    ret = kv_table_execute_operations(store, op, NULL, &resultp);
    if (ret != KV_SUCCESS) {
        printf("operation execution failed.\n");
    } else {
        printf("operation execution succeeded.\n");
    }

ERROR:
    /* Close the store handle. */
    if (store) {
        kv_close_store(&store);
    }

    if (resultp) {
        kv_release_operation_results(&resultp);
    }
    
    if (op) {
        kv_release_operations(&op);
    }

    return 0;
}

int
add_op_list(kv_operations_t *op, 
            const char *itemType, const char *itemCategory, 
            const char *itemClass, const char *itemColor,
            const char *itemSize, float price, int inventoryCount)
{
    kv_error_t ret;
    kv_row_t *row = NULL;

    row = kv_create_row();
    if (!row) {
        printf("row creation failed.\n");
        return -1;
    }

    ret = kv_row_put_string(row, "itemType", itemType);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemType' failed.\n");
        return -1;
    }

    ret = kv_row_put_string(row, "itemCategory", itemCategory);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemCategory' failed.\n");
        return -1;
    }

    ret = kv_row_put_string(row, "itemClass", itemClass);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemClass' failed.\n");
        return -1;
    }

    ret = kv_row_put_string(row, "itemColor", itemColor);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemColor' failed.\n");
        return -1;
    }

    ret = kv_row_put_string(row, "itemSize", itemSize);
    if (ret != KV_SUCCESS) {
        printf("row put 'itemSize' failed.\n");
        return -1;
    }

    ret = kv_row_put_float(row, "price", price);
    if (ret != KV_SUCCESS) {
        printf("row put 'price' failed.\n");
        return -1;
    }

    ret = kv_row_put_int(row, "inventoryCount", inventoryCount);
    if (ret != KV_SUCCESS) {
        printf("row put 'inventoryCount' failed.\n");
        return -1;
    }

    ret = kv_create_table_put_op(op, "myTable", row,
                  KV_RETURN_ROW_NONE, // kv_return_row_version_enum
                  0); // Abort on failure?
    if (ret != KV_SUCCESS) {
        printf("Store put op failed.\n");
        return -1;
    } else {
        printf("Store put op succeeded.\n");
    }

    // Do not release the row at the end of this, as doing so will 
    // cause the operation execution to core dump. The row must be 
    // saved for the future operation.
    //
    return KV_SUCCESS;
} 

一貫性保証の設定

デフォルトでは、読取り操作はKV_CONSISTENCY_NONEの一貫性保証で実行されます。次のいずれかの関数を使用して、このデフォルトをオーバーライドする一貫性保証を作成します。

  1. kv_create_simple_consistency()

  2. kv_create_time_consistency()

  3. kv_create_version_consistency()

これらは、kv_release_consistency()を使用して解放する必要のあるkv_consistency_t構造体の割当てと移入を行います。

次に、kv_consistency_t構造体をkv_create_read_options()とともに使用して、kv_read_options_t構造体の作成、割当ておよび移入を行います。kv_release_read_options()を使用して、この構造体を解放します。

最後に、ストアからの読取り操作を実行する場合はkv_read_options_t構造体を使用します。

たとえば、「単一の表の行の読取り」に示すコード・フラグメントは、次の方法でデフォルトの一貫性ポリシーを使用するようにリライトできます。

void
do_store_ops(kv_store_t *store)
{
    kv_consistency_t *consis = NULL;
    kv_error_t ret;
    kv_read_options_t *readopts = NULL;
    kv_result_t *results = NULL;
    kv_row_t *key = NULL;

    ret = kv_create_simple_consistency(KV_CONSISTENCY_ABSOLUTE, 
                                       &consis);
    if (ret != KV_SUCCESS) {
        printf("consistency creation failed\n");
        goto cleanup;
    }
    
    ret = kv_create_read_options(consis,  // consistency
                                 0,       // timeout value. 
                                          // 0 means use the default.
                                 &readopts);
    if (ret != KV_SUCCESS) {
        printf("readoptions creation failed\n");
        return;
    }

    key = kv_create_row();
    if (!key) {
       printf("key creation failed.\n");
       goto cleanup;
    }

    ret = kv_row_put_string(key, "item", "Bolts");
    if (ret != KV_SUCCESS) {
        printf("row put 'item' failed.\n");
        goto cleanup;
    }

    ret = kv_table_get_with_options(store, 
                                    "myTable", 
                                    key, 
                                    readopts,
                                    &results);
    if (ret != KV_SUCCESS) {
        printf("Retrieval failed.\n");
        goto cleanup;
    }
    
    kv_row_t *retRow = kv_result_get_row(results);

    const char *retItem = NULL, *retDescription = NULL;
    int retCount = 0;
    float retPercentage = 0.0;

    kv_row_get_string(retRow, "item", &retItem);
    kv_row_get_string(retRow, "description", &retDescription);
    kv_row_get_int(retRow, "count", &retCount);
    kv_row_get_float(retRow, "percentage", &retPercentage);

    printf("Item: %s. Desc: %s. Count is %i. Percent is %f\n",
            retItem, retDescription, retCount, retPercentage);

cleanup:
    if (key) {
        kv_release_row(&key);
    }

    if (retRow) {
        kv_release_row(&retRow);
    }

    // kv_release_read_options also releases the 
    // kv_consistency_t structure.
    if (readopts) {
        kv_release_read_options(&readopts);
    }
} 

永続性保証の設定

デフォルトでは、書込み操作はKV_DURABILITY_COMMIT_NO_SYNCの永続性保証で実行されます。これは、永続性保証を作成および使用することでオーバーライドできます。

kv_create_durability()を使用してkv_durability_t構造体を初期化します。次に、kv_durability_t構造体をkv_create_write_options()とともに使用して、kv_write_options_t構造体の割当てと移入を行います。kv_release_write_options()を使用して、この構造体を解放します。

最後に、ストアへの書込み操作を実行する場合はkv_write_options_t構造体を使用します。

たとえば、「表の行への書込み」に示すコード・フラグメントは、次の方法で永続性ポリシーを使用するようにリライトできます。

void
do_store_ops(kv_store_t *store)
{
    kv_error_t ret;
    kv_row_t *row = NULL;
    kv_durability_t durability;
    kv_write_options_t *writeopts;
    kv_result_t *results;

    row = kv_create_row();
    if (!row) {
       printf("row creation failed.\n");
       goto cleanup;
    }

    ret = kv_row_put_string(row, "item", "Bolts");
    if (ret != KV_SUCCESS) {
        printf("row put 'item' failed.\n");
        goto cleanup;
    }
    ret = kv_row_put_string(row, "description", "Hex head, stainless");
    if (ret != KV_SUCCESS) {
        printf("row put 'description' failed.\n");
        goto cleanup;
    }
    ret = kv_row_put_int(row, "count", 5);
    if (ret != KV_SUCCESS) {
        printf("row put 'count' failed.\n");
        goto cleanup;
    }

    ret = kv_row_put_float(row, "percentage", 0.2173913);
    if (ret != KV_SUCCESS) {
        printf("row put 'percentage' failed.\n");
        goto cleanup;
    }

    durability = kv_create_durability(
                    KV_SYNC_FLUSH, // Master sync
                    KV_SYNC_NONE,  // Replica sync
                    KV_ACK_MAJORITY); // Ack policy

    ret = kv_create_write_options(durability,
                                  0, // 0 is default timeout
                                  &writeopts);
    if (ret != KV_SUCCESS) {
        printf("Write options creation failed.\n");
        return;
    }   


    ret = kv_table_put_with_options(store, 
                                    "myTable", 
                                    row,
                                    writeopts,
                                    // Whether the new row should be
                                    // returned in the results 
                                    // parameter.
                                    KV_RETURN_ROW_NONE, 
                                    &results);

    if (ret != KV_SUCCESS) {
        printf("Store put failed.\n");
        goto cleanup;
    } else {
        printf("Store put succeeded.\n");
    }

cleanup:
    if (row) {
        kv_release_row(&row);
    }

    if (writeopts) {
        kv_release_write_options(&writeopts);
    }
    
    if (results) {
        kv_release_result(&results);
        }
} 

プロキシ・サーバー・リファレンス

プロキシ・サーバーのコマンドライン・オプションを次に示します。

nohup java -cp KVHOME/lib/kvclient.jar:kvproxy/lib/kvproxy.jar 
oracle.kv.proxy.KVProxy -help
 -port <port-number> Port number of the proxy server. Default: 5010
 -store <store-name> Required KVStore name. No default.
 -helper-hosts <host:port,host:port,...>   Required list of KVStore 
        hosts and ports (comma separated).
 -security <security-file-path>  Identifies the security file used 
        to specify properties for login. Required for connecting to 
        a secure store.
  -username <user>  Identifies the name of the user to login to the 
        secured store. Required for connecting to a secure store.
  -read-zones <zone,zone,...>  List of read zone names.
  -max-active-requests <int> Maximum number of active requests towards
        the store.
  -node-limit-percent <int> Limit on the number of requests, as a 
        percentage of the requested maximum active requests.
  -request-threshold-percent <int> Threshold for activating request 
        limiting, as a percentage of the requested maximum active 
        requests.
  -request-timeout <long> Configures the default request timeout in
        milliseconds.
  -socket-open-timeout <long> Configures the open timeout in 
        milliseconds used when establishing sockets to the store.
  -socket-read-timeout <long> Configures the read timeout in 
        milliseconds associated with the underlying sockets to the 
        store.
  -max-iterator-results <long> A long representing the maximum 
        number of results returned in one single iterator call. 
        Default: 100
  -iterator-expiration <long>  Iterator expiration interval in 
        milliseconds.
  -max-open-iterators <int>    Maximum concurrent opened iterators.
        Default: 10000
  -num-pool-threads <int>      Number of proxy threads. Default: 20
  -max-concurrent-requests <int>      The maximum number of 
        concurrent requests per iterator. Default: <num_cpus * 2>
  -max-results-batches <int>      The maximum number of results 
        batches that can be held in the proxy per iterator. 
        Default: 0
  -help  Usage instructions.
  -version  Print KVProxy server version number.
  -verbose  Turn verbose flag on.  

プロキシ・サーバーを起動する前に必ずOracle NoSQL Databaseストアを起動します。

非セキュア・ストアに接続するときは次のパラメータが必要です。

  • -helper-hosts

  • -port

  • -store

セキュア・ストアに接続するときは次のパラメータも必要です。

  • -security

  • -username

注意

ドライバは、正しく構成されている場合にローカル・ホスト上のプロキシ・サーバーを開始および停止できます。詳細は、「プロキシ・サーバーの自動的な起動」を参照してください。

Oracle NoSQL Databaseプロキシ・サーバーの保護

正しく構成されている場合、プロキシはOracle NoSQL Databaseの安全なインストールにアクセスできます。これを行うには、-usernameおよび-securityプロキシ・オプションを指定する必要があります。

次の例では、Oracle NoSQL Database単一ノード・デプロイメントにセキュリティを追加する方法を説明します。例では、Oracle NoSQL Databaseレプリケーション・ノードへの接続を開始する方法も示します。

Oracle NoSQL Databaseをセキュアにインストールする手順は、次のとおりです。

java -Xmx256m -Xms256m \
-jar KVHOME/lib/kvstore.jar makebootconfig \
-root KVROOT -port 5000 \
-admin 5001 -host node01 -harange 5890,5900 \
-store-security configure -pwdmgr pwdfile -capacity 1 
  1. makebootconfigユーティリティを必要な-store-securityオプションとともに実行して、セキュリティを備えた基本ストア構成を設定します。

  2. この例では、-store-security configureが使用されるため、security configurationユーティリティがmakebootconfigプロセスの一部として実行され、キーストア・ファイルに使用するパスワードの入力が求められます。

    Enter a password for the Java KeyStore: 
  3. ストアのパスワードを入力してから、検証のために再入力します。この場合、パスワード・ファイルが使用され、securityconfigツールによって次のセキュリティ関連ファイルが自動生成されます。

    Enter a password for the Java KeyStore: ***********
    Re-enter the KeyStore password for verification: ***********
    Created files:
    security/client.trust
    security/client.security 
    security/store.keys
    security/store.trust
    security/store.passwd
    security/security.xml 

    注意

    マルチホスト・ストア環境では、securityディレクトリおよびここに含まれるすべてのファイルを、ストレージ・ノードをホストする各サーバーにコピーする必要があります。複数ノード・デプロイメントの詳細は、『Oracle NoSQL Databaseセキュリティ・ガイド』を参照してください。

  4. ストレージ・ノード・エージェント(SNA)を起動します。

    nohup java -Xmx256m -Xms256m \
    -jar KVHOME/lib/kvstore.jar start -root KVROOT&

    セキュアな構成の新規作成されたストアの初回起動時には、アクセスを認証するための使用可能なユーザー定義がありません。不正アクセスのリスクを抑えるために、管理者によって許可されるのは実行中のホストからの接続のみとなります。このセキュリティ手段は、不正アクセスに対する完全な予防策にはなりません。KVStoreが動作するマシンへのローカル・アクセスを可能にしないことが重要です。また、完全認証なしで管理者がアクセスできる期間を最小限にするために、このステップの直後にステップ5、6および7を実行する必要があります。安全なストアのメンテナンスの詳細は、『Oracle NoSQL Databaseセキュリティ・ガイド』を参照してください。

  5. KVStoreサーバー・ホスト(node01)上で、runadminをセキュリティ・モードで起動します。このためには、次のコマンドを使用します。

    java -Xmx256m -Xms256m \
    -jar KVHOME/lib/kvstore.jar \
    runadmin -port 5000 -host node01 \
    -security KVROOT/security/client.security
    Logged in admin as anonymous 
  6. configure -nameコマンドを使用すると、構成するKVStoreの名前を指定できます。

    kv-> configure -name mystore
    Store configured: mystore 
  7. ゾーン、ストレージ・ノードおよび管理ノードをデプロイすることでKVStoreを構成します。次に、ストレージ・ノード・プールを作成します。最後に、トポロジを作成してデプロイします。

    kv-> plan deploy-zone -name mydc -rf 1 -wait
    Executed plan 2, waiting for completion...
    Plan 2 ended successfully
    kv-> plan deploy-sn -zn zn1 -port 5000 -host node01 -wait
    Executed plan 3, waiting for completion...
    Plan 3 ended successfully
    kv-> plan deploy-admin -sn sn1 -port 5001 -wait
    Executed plan 4, waiting for completion...
    Plan 4 ended successfully
    kv-> pool create -name mypool
    kv-> pool join -name mypool -sn sn1
    Added Storage Node(s) [sn1] to pool mypool
    kv-> topology create -name mytopo -pool mypool -partitions 30
    Created: mytopo
    kv-> plan deploy-topology -name mytopo -wait
    Executed plan 5, waiting for completion...
    Plan 5 ended successfully 
  8. 管理ユーザーを作成します。この場合、ユーザーrootが定義されます。

    kv-> plan create-user -name root -admin -wait
    Enter the new password: ********
    Re-enter the new password: ********
    Executed plan 6, waiting for completion...
    Plan 6 ended successfully  
  9. 新規パスワード・ファイルを作成し、クライアントに対して管理ユーザー(root)としてのログインを許可するために必要な資格証明を格納します。

    java -Xmx256m -Xms256m \
    -jar KVHOME/lib/kvstore.jar securityconfig \
    pwdfile create -file KVROOT/security/login.passwd
    java -Xmx256m -Xms256m \
    -jar KVHOME/lib/kvstore.jar securityconfig pwdfile secret \
    -file KVROOT/security/login.passwd -set -alias root 
    Enter the secret value to store: ********
    Re-enter the secret value for verification: ********
    Secret created
    OK

    注意

    パスワードは、前のステップで管理用に設定したパスワードと一致する必要があります。

  10. この時点では、rootユーザーとしてストアに接続できます。ログインするには、-username <user> runadmin引数を使用するか、セキュリティ・ファイルに"oracle.kv.auth.username"プロパティを指定します。

    この例では、セキュリティ・ファイル(mylogin.txt)が使用されます。ログインするには、次のコマンドを使用します。

    java -Xmx256m -Xms256m \
    -jar KVHOME/lib/kvstore.jar runadmin -port 5000 \
    -host localhost -security mylogin
    Logged in admin as root 

    ファイルmylogin.txtは、認証用に追加のプロパティ設定が含まれる、client.securityファイルのコピーである必要があります。このファイルには次のような内容が含まれます。

    oracle.kv.auth.username=root
    oracle.kv.auth.pwdfile.file=KVROOT/security/login.passwd
    oracle.kv.transport=ssl
    oracle.kv.ssl.trustStore=KVROOT/security/client.trust
    oracle.kv.ssl.protocols=TLSv1.2,TLSv1.1,TLSv1
    oracle.kv.ssl.hostnameVerifier=dnmatch(CN\=NoSQL) 

さらに、KVProxyを実行し、安全なOracle NoSQL Databaseデプロイメントにアクセスするには、次のようにします。

java -cp KVHOME/lib/kvclient.jar:KVPROXY/lib/kvproxy.jar 
oracle.kv.proxy.KVProxy -helper-hosts node01:5000 -port 5010 
-store mystore -username root -security mylogin 
Nov 21, 2014 12:59:12 AM oracle.kv.proxy.KVProxy <init>
INFO: PS: Starting KVProxy server
Nov 21, 2014 12:59:12 AM oracle.kv.proxy.KVProxy <init>
INFO: PS: Connect to Oracle NoSQL Database mystore nodes : localhost:5000
Nov 21, 2014 12:59:13 AM oracle.kv.proxy.KVProxy <init>
INFO: PS:   ... connected successfully
Nov 21, 2014 12:59:13 AM oracle.kv.proxy.KVProxy startServer
INFO: PS: Starting listener ( Half-Sync/Half-Async server - 20
no of threads on port 5010) 

注意

このプロキシ・サーバーは安全なストアで使用されているため、プロキシ・サーバーのリスニング・ポート(前の例ではポート5010)を、認可されたクライアントを実行しているホストのみに制限する必要があります。

プロキシ・サーバーのトラブル・シューティング

クライアントがストアに接続できない場合、クライアント・コード、プロキシとその構成、またはストアに問題がある可能性があります。何が問題になるかを判断するためには、クライアント・コードがストアに接続するときに何が起きるかをよく理解することが役立ちます。

  1. まず、クライアント・コードはプロキシで指定されたip:portペアに接続しようとします。

  2. 接続の試行が失敗し、プロキシが自動的に起動する必要があるとクライアント・コードによって通知された場合:

    1. クライアント・ドライバは、ローカル・ホストでプロキシを起動するコマンドラインを準備します。このコマンドラインに含まれるのは、javaコマンドのパス、プロキシの起動に必要な2つのjarファイルのクラスパス、プロキシを起動しストアに接続するために必要なパラメータ(リスニングするプロキシのローカル・ポートやストアの接続情報が含まれる)です。

    2. ドライバがコマンドラインを実行します。問題が発生した場合、問題の正確な特徴によって異なりますが、関連するエラー情報をドライバが提供できる場合があります。

    3. コマンドを実行すると、ドライバは接続が完了するまで数秒間待機します。この間にプロキシが起動を試行します。この時点では、クラスパスの問題が示されることがあります。

      次に、kvclient.jarのバージョンをチェックし、適合していない場合は知らせます。

      その後、接続パラメータをチェックし、問題があれば知らせます。

      次に、プロキシがhelper-hostsパラメータを使用して実際にストアに接続します。この時点では、ストアにアクセスできない、セキュリティ資格証明がない、またはセキュリティ資格証明が正しくないといった、接続エラーが報告されることがあります。

      最後に、プロキシは指定のポートのリスニングを試行します。ポートのリスニング中にエラー(別のプロセスで使用中など)が発生すると、プロキシによって報告されます。

    4. 直前の手順でエラーが発生すると、ドライバは自動的にプロセス全体を繰り返します。正常に接続を取得するか、再試行回数に到達するまで、プロセスを繰り返し続けます。

      最終的にドライバが接続を正常に確立できない場合、エラーを返します。

  3. ドライバが正常にプロキシに接続した場合、プロキシに確認メッセージを送信します。この確認メッセージには、helper-hostリスト、ストア名、ユーザー名(セキュア・ストアを使用している場合)、読取りゾーン(ストアで使用される場合)が含まれます。

    確認メッセージの情報に問題がある場合、プロキシがエラー・メッセージを返します。これにより、ドライバが正しいストアに接続していることを確認するために、プロキシがパラメータをチェックします。

  4. 確認メッセージにエラーがない場合は、接続が確立され、ストアの操作を実行することができます。

接続の問題をトラブルシューティングする際に最適なエラー情報を取得するには、-verboseコマンドライン・オプションを使用してプロキシを起動します。また、java -eaコマンドライン・オプションを使用するとプロキシJavaコードのアサーションを有効化できます。

これら2つのメカニズムによりプロキシは豊富な情報を提供します。分析するためにファイルへのロギングを有効にすることができます。これを行う手順は次のとおりです。

次のパラメータを使用してプロキシを起動します。

java -cp KVHOME/lib/kvclient.jar:KVPROXY/lib/kvproxy.jar  
-Djava.util.logging.config.file=logger.properties 
oracle.kv.proxy.KVProxy -helper-hosts node01:5000 -port 5010 
-store mystore -verbose 

ファイルlogger.propertiesには次のような内容が含まれます。

# Log to file and console
handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
## ConsoleHandler ##
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = 
                                       java.util.logging.SimpleFormatter
## FileHandler ##
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
# Limit the size of the file to x bytes
java.util.logging.FileHandler.limit = 100000
# Number of log files to rotate
java.util.logging.FileHandler.count = 1
# Location and log file name
# %g is the generation number to distinguish rotated logs
java.util.logging.FileHandler.pattern = ./kvproxy.%g.log

構成パラメータは、使用される回転ログ・ファイルのサイズおよび数を制御します(これはjavaロギングに似ています。java.util.logging.FileHandlerを参照してください)。回転ファイル・セットの場合、各ファイルが指定されたサイズ制限に達すると、ファイルが閉じられて回転された後、新しいファイルが開かれます。古いファイルにはファイル名に"0"、"1"、"2"などを追加することで連続的に名前が付けられます。