2011年2月19日土曜日

Go + SWIG + Cassandra + Thrift (3)

前回まででCassandraにサンプルデータが入ったので、今回はその値を取り出すC++のサンプルを作成する。

Cassandraとインタフェースするためのクラスを生成

前回挿入したデータをC++上から取得するにはThriftを使用する必要がある。そこで、まずはThriftを使ってCassandraとインタフェースするためのクラスを生成する。

$ thrift --gen cpp ~/lib/cassandra/interface/cassandra.thrift
$ ls gen-cpp/
cassandra_constants.cpp  Cassandra.cpp  Cassandra_server.skeleton.cpp  cassandra_types.h
cassandra_constants.h    Cassandra.h    cassandra_types.cpp

上記のコマンドで生成されたクラスと、Thriftのライブラリを組み合わせることによってCassandraと通信できるようになる。

Cassandraからデータを取り出すサンプル

#include <string>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>

#include <boost/shared_ptr.hpp>
#include <protocol/TBinaryProtocol.h>
#include <transport/TSocket.h>
#include <transport/TTransportUtils.h>

// auto-generated thrift interface code using cassandra.thrift in cassandra repository
#include "Cassandra.h"

using boost::shared_ptr;
using apache::thrift::protocol::TProtocol;
using apache::thrift::protocol::TBinaryProtocol;
using apache::thrift::transport::TSocket;
using apache::thrift::transport::TTransport;
using apache::thrift::transport::TFramedTransport;
using org::apache::cassandra::CassandraClient;
using org::apache::cassandra::ColumnOrSuperColumn;
using org::apache::cassandra::Column;
using org::apache::cassandra::ColumnPath;
using org::apache::cassandra::ConsistencyLevel;
using org::apache::cassandra::KsDef;
using org::apache::cassandra::InvalidRequestException;
using org::apache::cassandra::NotFoundException;
using apache::thrift::TException;
using std::string;

static void describeServer(shared_ptr<CassandraClient> client, string keyspace) {
    string ver;
    client->describe_version(ver);

    string name;
    client->describe_cluster_name(name);

    KsDef keyspaceDescription;
    client->describe_keyspace(keyspaceDescription, keyspace);

    printf("Server:\n  version: %s\n  name: %s\n", ver.c_str(), name.c_str());
    printf("  keyspace: %s\n  strategy class: %s\n",
           keyspaceDescription.name.c_str(),
           keyspaceDescription.strategy_class.c_str());
}

static void printColumn(const Column &col) {
    printf("Column:\n  name: %s\n  value: %s\n  timestamp: %lld\n  ttl: %d\n",
           col.name.c_str(),
           col.value.c_str(),
           col.timestamp,
           col.ttl);
}

int main(int argc, char **argv) {
    const string host = "localhost";
    int port = 9160;
    shared_ptr<TTransport> socket(new TSocket("localhost", port));
    shared_ptr<TTransport> transport(new TFramedTransport(socket));
    shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
    shared_ptr<CassandraClient> client(new CassandraClient(protocol));
    transport->open();

    const string keyspace = "sample_keyspace";

    describeServer(client, keyspace);
    
    client->set_keyspace(keyspace);

    string columnFamily = "SampleColumnFamily";
    string columnKey = "SampleColumn";
    string columnName = "SampleName";
    ColumnPath path;
    path.__isset.column = true;
    path.column_family = columnFamily;
    path.column = columnName;

    ColumnOrSuperColumn output;
    try {
        client->get(output,
                    columnKey,
                    path,
                    ConsistencyLevel::ONE);
    } catch (InvalidRequestException &re) {
        printf("ERROR: InvalidRequest. %s\n",re.why.c_str());
    } catch (NotFoundException &e) {
        printf("ERROR: NotFound. %s\n",e.what());
    }

    printColumn(output.column);

    transport->close();
}

ビルド方法

最初にThriftで生成したソース、及び上のサンプルを記述したsample.cppを合わせてビルドする。

$ g++ -Wall sample.cpp gen-cpp/cassandra_types.cpp gen-cpp/cassandra_constants.cpp gen-cpp/Cassandra.cpp -I/usr/local/include/thrift -I./gen-cpp -lthrift

実行結果

$ ./a.out
Server:
  version: 19.4.0
  name: Test Cluster
  keyspace: sample_keyspace
  strategy class: org.apache.cassandra.locator.SimpleStrategy
Column:
  name: SampleName
  value: SampleValue
  timestamp: 1297591990231000
  ttl: 0

(続く)

0 件のコメント:

コメントを投稿