法律上の注意点
Copyright © 2011, 2012, 2013, 2014, Oracle and/or its affiliates.All 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の登録商標です。
このソフトウェアまたはハードウェアおよびドキュメントは、第三者のコンテンツ、製品、サービスへのアクセス、あるいはそれらに関する情報を提供することがあります。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスに関して一切の責任を負わず、いかなる保証もいたしません。オラクル社およびその関連会社は、第三者のコンテンツ、製品、サービスへのアクセスまたは使用によって損失、費用、あるいは損害が発生しても、一切の責任を負いかねます。
12/5/2014
目次
この記事では、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 APIからのネットワーク・トラフィックを受け入れ、Oracle NoSQL Databaseストアが理解できるリクエストに変換してから、変換したリクエストをストアに転送するJavaアプリケーションです。プロキシは、ストアのレスポンスを解釈し、それらをクライアントに転送する逆変換サービスも提供します。
プロキシ・サーバーは、ネットワーク・アクセス可能な任意のマシンで実行できます。リソース要件は最小限で、多くの場合、クライアント・ノードが実行されているのと同じマシンで実行できます。
Cクライアントがストアにアクセスするには、プロキシ・サーバーが実行されている必要があります。java -cp
コマンド・ライン・オプションを使用するかCLASSPATH
環境変数を使用することで、クラス・パスに次のjarファイルが設定されている必要があります。
KVHOME/lib/kvclient.jar
.../kv-c-driver-X.Y.Z/kvproxy/lib/kvproxy.jar
プロキシ・サーバー自体は、oracle.kv.proxy.KVProxy
コマンドを使用して起動します。少なくとも、プロキシ・サーバーの起動時には次の情報が必要です。
-helper-hosts
これは、プロキシ・サーバーがストアへの接続に使用できるOracle NoSQL Databaseストレージ・ノードを表す1つ以上のホスト:ポート・ペアのリストです。
-port
クライアント・コードがプロキシ・サーバーのこのインスタンスに接続できるポート。
他の一連のコマンド・ライン・オプションを使用できます。特に、安全なストアでプロキシ・サーバーを使用している場合は、プロキシ・サーバーに認証情報を提供する必要があります。また、プロキシ・サーバーにストア名を識別することが必要になる可能性があります。プロキシ・サーバーとそのコマンド・ライン・オプションの詳細な説明は、プロキシ・サーバー・リファレンスを参照してください。
このクイック・スタート・ガイドで提供している単純な例は、デフォルト値で起動されたkvlite
インスタンスに接続しているプロキシ・サーバーで動作するように作成されています。kvclient.jar
およびkvproxy.jar
ファイルの場所は、CLASSPATH
環境変数を使用して提供されています。プロキシ・サーバーの起動に使用したコマンド・ライン・コールは次のとおりです。
nohup java oracle.kv.proxy.KVProxy -port 7010 \ -helper-hosts localhost:5000
Cクライアントをコンパイルするには、libkvstore.so
またはlibkvstore-static.a
をリンクします。これらは、cmake
に提供したインストール場所に含まれるlib
ディレクトリにあります。
.so
ファイルを使用する場合は、実行時にライブラリが見つかるように、LD_LIBRARY_PATH
環境変数にインストール・ディレクトリを追加してください。
kvstore.h
ヘッダー・ファイルは、cmake
に提供したインストール場所に含まれるinclude
ディレクトリにあります。
ストア操作を実行するには、クライアント・コードとストア間にネットワーク接続を確立する必要があります。提供する必要のある2つの情報があります。
kv_config_t
構造を使用して、ストアの名前、ホストおよびポートを識別します。この構造に提供するホストとポートは、ストア内のノードをホストする任意のマシンです。(ストアは多くのホストから構成されるため、複数のホスト/ポートのペアから選択する必要があります。)
kv_config_t
構造体を作成するにはkv_create_config()
を使用します。構造体はkv_release_config()
を使用して解放できます。
プロキシが実行されているホストとポートを識別します。これは、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_t
とkv_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 1
とBLOCK 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
の一貫性保証で実行されます。次のいずれかの関数を使用して、このデフォルトをオーバーライドする一貫性保証を作成します。
kv_create_simple_consistency()
kv_create_time_consistency()
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); }
}
KVStoreインスタンスが起動し、稼働したら、次のコマンドを使用してプロキシを開始します。
nohup java -cp KVHOME/lib/kvclient.jar:kvproxy/lib/kvproxy.jar oracle.kv.proxy.KVProxy -helper-hosts <host:port,host:port,...> [-help] [-iterator-expiration <long>] [-max-active-requests <int>] [-max-iterator-results <long>] [-max-open-iterators <int>] [-node-limit-percent <int>] [-num-pool-threads <int>] [-port <port-number>] [-read-zones <zone,zone, ...>] [-request-threshold-percent <int>] [-request-timeout <long>] [-security <security-file-path>] [-socket-open-timeout <long>] [-socket-read-timeout <long>] [-store <store-name>] [-username <user>] [-version] [-verbose]
それぞれの意味は次のとおりです。
-help
プロキシ・コマンドに対して使用可能なすべてのパラメータの使用方法とリストを表示します。
-helper-hosts <host:port,host:port,...>
KVStoreホストおよびポートのリストを識別します。このパラメータを指定する必要があります。
-iterator-expiration <long>
イテレータの失効間隔をミリ秒単位で指定します。
-max-active-requests <int>
ストアに転送される同時アクティブ・リクエストの最大数を指定します。
-max-iterator-results <long>
1回のイテレータ・コールで返される結果の最大数を指定します。デフォルト値は100です。
-max-open-iterators <int>
同時に開かれるイテレータの最大数を指定します。デフォルト値は10000です。
-node-limit-percent <int>
リクエスト制限の数を、リクエストされる最大アクティブ・リクエスト数の割合として指定します。
-num-pool-threads <int>
プロキシ・スレッド数を指定します。デフォルト値は20です。
-port
プロキシがリスニングするポート番号を識別します。デフォルト値は5010です。
-read-zones <zone, zone, ...>
読取りゾーン名のリスト。
-request-threshold-percent <int>
リクエスト制限のアクティブ化のしきい値を、リクエストされる最大アクティブ・リクエスト数の割合として指定します。
-request-timeout <long>
デフォルトのリクエスト・タイムアウトをミリ秒単位で構成します。
-security <security-file-path>
ログインのプロパティを指定するために使用されるセキュリティ・ファイルを識別します。安全なストアへの接続に必要です。
-socket-open-timeout <long>
ストアへのソケットを確立する際に使用されるオープン・タイムアウトをミリ秒単位で構成します。
-socket-read-timeout <long>
ストアへの基礎となるソケットに関連付けられた読取りタイムアウトをミリ秒単位で構成します。
-store
ストアの名前を識別します。デフォルト値はkvstore
です。
-username <user>
保護されたストアにログインするユーザーの名前を識別します。安全なストアへの接続に必要です。
-verbose
コマンドの冗長出力を有効にします。
-version
プロキシ・サーバーのバージョン番号を表示します。
ドライバは、正しく構成されている場合にローカル・ホスト上のプロキシ・サーバーを開始および停止できます。詳細は、「プロキシ・サーバーの自動的な起動」を参照してください。
正しく構成されている場合、プロキシは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
makebootconfig
ユーティリティを必要な-store-security
オプションとともに実行して、セキュリティを備えた基本ストア構成を設定します。
この例では、-store-security configure
が使用されるため、security configuration
ユーティリティがmakebootconfigプロセスの一部として実行され、キーストア・ファイルに使用するパスワードの入力が求められます。
Enter a password for the Java KeyStore:
ストアのパスワードを入力してから、検証のために再入力します。この場合、パスワード・ファイルが使用され、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セキュリティ・ガイド』を参照してください。
ストレージ・ノード・エージェント(SNA)を起動します。
nohup java -Xmx256m -Xms256m \ -jar KVHOME/lib/kvstore.jar start -root KVROOT&
セキュアな構成の新規作成されたストアの初回起動時には、アクセスを認証するための使用可能なユーザー定義がありません。不正アクセスのリスクを抑えるために、管理者によって許可されるのは実行中のホストからの接続のみとなります。このセキュリティ手段は、不正アクセスに対する完全な予防策にはなりません。KVStoreが動作するマシンへのローカル・アクセスを可能にしないことが重要です。また、完全認証なしで管理者がアクセスできる期間を最小限にするために、このステップの直後にステップ5、6および7を実行する必要があります。安全なストアのメンテナンスの詳細は、『Oracle NoSQL Databaseセキュリティ・ガイド』を参照してください。
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
configure -name
コマンドを使用すると、構成するKVStoreの名前を指定できます。
kv-> configure -name mystore Store configured: mystore
ゾーン、ストレージ・ノードおよび管理ノードをデプロイすることで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
管理ユーザーを作成します。この場合、ユーザー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
新規パスワード・ファイルを作成し、クライアントに対して管理ユーザー(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
パスワードは、前のステップで管理用に設定したパスワードと一致する必要があります。
この時点では、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)を、認可されたクライアントを実行しているホストのみに制限する必要があります。