前々回はAWS SDK for C++を使ってS3をいじってみました。今回はDynamoDBで試してみます。せっかくなのでDynamoDB Localをdockerで動かし、それを操作します。
#準備
まずはdockerでDynamoDB Localを動かします。
##dockerでDynamoDB Localを動かす
丁度よさげなイメージがこちらにありましたので、これを使って動かします。その際に-sharedDbを指定し、リージョン区分のエミュレート機能を無効にします。個人的にはこの機能はハマりポイントだと思うので(というかハマりました)無効にして単一のDBが作られるようにします。
$ sudo docker run -d \
-p 8000:8000 \
-v /var/dynamodblocal:/var/dynamodblocal \
--name localdynamodb \
-t tray/dynamodb-local -sharedDb -dbPath /var/dynamodblocal
DynamoDB Localにテーブルを作成
動かしたら次はaws cli
でテーブルを作ります。
開発者ガイドをパクって、Music という名前のテーブルを作成します。パーティションキーは Artist で、ソートキーは SongTitle です。
DynamoDB Localに作るので--endpoint-url http://localhost:8000
を指定しています。
$ aws dynamodb create-table --endpoint-url http://localhost:8000 \
--table-name Music \
--attribute-definitions AttributeName=Artist,AttributeType=S \
AttributeName=SongTitle,AttributeType=S \
--key-schema AttributeName=Artist,KeyType=HASH AttributeName=SongTitle,KeyType=RANGE \
--provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
DynamoDB JavaScript Shellを使って見てみる
http://localhost:8000/shell/ を開いてDynamoDB JavaScript ShellでDBにテーブルが作られたことを確認します。
こちらがテーブルの一覧を表示させるAPIです。
dynamodb.listTables(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});
実行するとこのように表示されて、Musicテーブルが作られたことが確認できます。
{"TableNames":["Music"]}
また、こちらのAPIを実行するとMusicテーブルの中身を覗けます。
var params = {
TableName: 'Music',
};
dynamodb.scan(params, function(err, data) {
if (err) print(err); // an error occurred
else print(data); // successful response
});
まだ何もありません。
{
"Items": [],
"Count": 0,
"ScannedCount": 0
}
AWS SDK for C++を使ってDynamoDB Localにputする
さて、AWS SDK for C++を使ってputしようと思いますが、そのための実行環境として拙作のこちらのイメージを使おうと思います。
※余談
このイメージをDocker Hubでビルドしますと現状、必ず失敗します。ライブラリをmakeするときにメモリを使い過ぎるのが原因かな、と思ってます。1ヶ月くらい前の時点では失敗したり成功したりでしたが、今は何回ビルドしても成功しません。なんとかして解決したいものです。
コンテナを起動してプログラムを実行
まずはコンテナを起動します。
$ sudo docker run -i --link localdynamodb:localdynamodb -t d9magai/awssdkcpp bash
コンテナを起動したらprog.cpp
を書きます。Musicテーブルに歌手名と曲名と再生回数をputするプログラムです。
#include <aws/core/Aws.h>
#include <aws/dynamodb/DynamoDBClient.h>
#include <aws/dynamodb/model/PutItemRequest.h>
#include <aws/dynamodb/model/AttributeValueValue.h>
#include <aws/core/auth/AWSCredentialsProvider.h>
#include <aws/core/utils/Outcome.h>
const Aws::String AWS_ACCESS_KEY_ID = "XXXXXXXXXXXXXXXXXXXX";
const Aws::String AWS_SECRET_ACCESS_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
int main(int argc, char** argv) {
try {
Aws::SDKOptions options;
Aws::InitAPI(options);
Aws::Client::ClientConfiguration config;
config.scheme = Aws::Http::Scheme::HTTP;
config.connectTimeoutMs = 1000;
config.requestTimeoutMs = 1000;
config.endpointOverride = "localdynamodb:8000";
config.region = Aws::Region::AP_NORTHEAST_1;
auto dynamoDbClient = Aws::DynamoDB::DynamoDBClient(Aws::Auth::AWSCredentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY), config);
Aws::DynamoDB::Model::PutItemRequest putItemRequest = Aws::DynamoDB::Model::PutItemRequest()
.WithTableName("Music")
.AddItem("Artist", Aws::DynamoDB::Model::AttributeValue().SetS("aiko"))
.AddItem("SongTitle", Aws::DynamoDB::Model::AttributeValue().SetS("アンドロメダ"))
.AddItem("Views", Aws::DynamoDB::Model::AttributeValue().SetN("3002"));
auto putItemOutcome = dynamoDbClient.PutItem(putItemRequest);
if(!putItemOutcome.IsSuccess()) {
std::stringstream ss;
ss << "PutItem failed with error: " << putItemOutcome.GetError().GetMessage() << std::endl;
throw std::runtime_error(ss.str());
}
std::cout << "PutItem Success" << std::endl;
Aws::ShutdownAPI(options);
} catch (const std::exception &e) {
std::cerr << e.what();
return 1;
}
return 0;
}
接続先がDynamoDB Localなので、アクセスキーもシークレットキーもダミーで構いません。
コンパイルして実行してPutItem Success
と表示されれば成功です。
$ g++ -DAWS_CUSTOM_MEMORY_MANAGEMENT -std=c++11 prog.cpp -I/opt/aws-sdk-cpp/include -L/opt/aws-sdk-cpp/lib/linux/intel64/ -laws-cpp-sdk-core -laws-cpp-sdk-dynamodb
$ ./a.out
PutItem Success
DynamoDB JavaScript ShellでMusicテーブルの中を見てみる
Musicテーブルの中身を確認し、ちゃんとデータがputされてるか見てみます。
http://localhost:8000/shell/ をもう一度開き、こちらのAPIでMusicテーブルをscanします。
var params = {
TableName: 'Music',
};
dynamodb.scan(params, function(err, data) {
if (err) print(err); // an error occurred
else print(data); // successful response
});
ちゃんと登録されていたら、こんな感じで表示されます。
{
"Items": [
{
"Artist": "aiko",
"SongTitle": "アンドロメダ",
"Views": 3002
}
],
"Count": 1,
"ScannedCount": 1
}
DynamoDB LocalとAWS SDK for C++をdockerで動かせた
無事に動かせました。
ちなみにアクセスキー、シークレットキーとAws::Client::ClientConfiguration config;
の値を正しく設定すればLocalではないほうのDynamoDBにも接続できます。今のところ私がAWS SDK for C++で使ったことがあるのはS3,DynamoDBくらいなので、もっと勉強していろいろ使ってみようと思います。
参考
https://aws.amazon.com/jp/blogs/aws/introducing-the-aws-sdk-for-c/