Symfoware

Symfowareについての考察blog

Voldemortをjmxでリモート監視する

Cassandraをインストールして動かしたとき、Jconsoleを使用して
監視してみました。
Cassandraの状態をJconsoleを使用して監視する


Voldemortにも同様のことが出来そうなので、調べてみました。




設定ファイルの編集



デフォルトでは、外部からjmxの機能に接続できませんでした。

JMX を使用する監視と管理
ここを参考に、Voldemortの起動スクリプトを編集します。


# vi bin/voldemort-server.sh




起動スクリプトの末尾のほうに


if [ -z $VOLD_OPTS ]; then
  VOLD_OPTS="-Xmx2G -server -Dcom.sun.management.jmxremote"
fi



こんな記載があると思います。
これを、以下のように編集します。
※ポート番号は適当です。


if [ -z $VOLD_OPTS ]; then
  VOLD_OPTS="-Xmx2G -server -Dcom.sun.management.jmxremote.port=8080 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"
fi







Jconsoleからの接続



接続する文字列は、Cassandraのときと同じく、


service:jmx:rmi:///jndi/rmi://[サーバーのIP]:8080/jmxrmi


でOKです。


接続してみると、こんな感じでメモリーやCPUの状況、ロードされているクラスなどが
確認できます。

02_001_20100416173237.png





テーマ:データベース - ジャンル:コンピュータ

  1. 2010/04/27(火) 12:11:12|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

VoldemortにPythonから登録したThrift形式のデータをJavaで取得する

JavaからThriftでシリアライズしたデータをVoldemortに登録。
Pythonで登録されたデータを読み込むことに成功しました。
VoldemortにJavaから登録したThrift形式のデータをPythonで取得する


今度は、PythonからThriftでシリアライズしたデータをVoldemortに登録。
Javaで登録されたデータを読み込んでみます。



Pythonのソース



Pythonのソースコードはこんな感じになりました。


# -*- coding:utf-8 -*-

import logging
import time

#Voldemortアクセス用
from voldemort import StoreClient

#Thriftを使用するため
from thrift.protocol import TBinaryProtocol
from thrift.transport import TTransport

#symfoware.thriftから生成したモジュール
import sys
sys.path.append('./gen-py')
from symfoware.voldemort.ttypes import ThriftData

if __name__ == '__main__':
    
    logging.basicConfig(level=logging.INFO,)
    
    #StoreClientを生成
    s = StoreClient('test', [('192.168.1.250', 6666)])
    
    
    td = ThriftData()
    td.title = "Pythonから"
    td.details = "登録したデータです"
    
    td.list_sample = []
    td.list_sample.append("日本語1")
    td.list_sample.append("日本語2")
    td.list_sample.append("日本語3")
    
    buf = TTransport.TMemoryBuffer()
    protocol = TBinaryProtocol.TBinaryProtocol(buf)
    
    td.write(protocol)
    
    s.put("key", buf.getvalue())



実行して、データを登録しておきます。





Javaのソース



Javaのソースはこんな感じ。


package com.fc2.blog68.symfoware.voldemort;

import voldemort.client.ClientConfig;
import voldemort.client.SocketStoreClientFactory;
import voldemort.client.StoreClient;
import voldemort.client.StoreClientFactory;

public class Sample {
    public static void main(String[] args) {
        
        String[] bootstrapUrls = new String[]{"tcp://192.168.1.250:6666"};
        
        ClientConfig cc = new ClientConfig();
        cc.setBootstrapUrls(bootstrapUrls);
        
        StoreClientFactory factory = new SocketStoreClientFactory(cc);
        
        //最初にキーの型、二番目に登録するデータの型を定義する
        StoreClient<String, ThriftData> client = factory.getStoreClient("test");
        
        //Pythonから登録したデータを検索
        ThriftData data = client.getValue("key");
        System.out.println(data.getTitle());
        System.out.println(data.getDetails());
        
        for (int i = 0; i < data.getList_sampleSize(); i++) {
            System.out.println(data.getList_sample().get(i));
        }
        
        factory.close();

    }
}






実行してみると・・・



[2010-04-24 16:34:06,059 voldemort.client.DefaultStoreClient] INFO bootstrapping metadata.
Pythonから
登録したデータです
日本語1
日本語2
日本語3




狙い通り。





テーマ:データベース - ジャンル:コンピュータ

  1. 2010/04/26(月) 12:09:22|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

VoldemortにJavaから登録したThrift形式のデータをPythonで取得する

JavaからThriftを使用してオブジェクトをシリアライズ。
シリアライズしたデータを登録してみました。
Voldemortのデータにオブジェクトを登録する方法(thrift使用)

この登録したデータをPythonで取得してみます。




データ登録の仕組み



JavaからThriftを使用してオブジェクトをシリアライズ。
シリアライズしたデータを登録という流れを図にしてみました。

01_001_20100416163821.png

このように、Voldemort側では渡されたデータをそのまま登録しており、
シリアライズはクライアント側で行われます。

そのため、Pythonでデータを読み取るときには、プログラム内で
シリアライズされたデータを解いてやればよいことになります。

01_002_20100416163821.png





Pythonの雛形準備



Javaからデータを登録するときに使用したthriftファイルから、
python用の雛形を生成してやります。

■voldemort.thrift


namespace java com.fc2.blog68.symfoware.voldemort
namespace py symfoware.voldemort

struct ThriftData {
    1:string title,
    2:string details,
    3:list<string> list_sample,
}





このthriftファイルからpythonの雛形を生成するコマンドは、


thrift --gen py voldemort.thrift



これで、gen-pyというディレクトリが出来ると思いますので、
これから作成するプログラムと同じ階層にコピーしておきます。






Pythonのサンプルプログラム



Debian + VoldemortにWindows + Pythonで接続する
まずは、ここでやったようにProtocol BuffersのPythonモジュールのインストールと、
voldemort.py
voldemort_client_pb2.py
のコピーを行っておきます。

ソースはこんな感じになりました。


# -*- coding:utf-8 -*-

import logging
import time

#Voldemortアクセス用
from voldemort import StoreClient

#Thriftを使用するため
from thrift.protocol import TBinaryProtocol
from thrift.transport import TTransport

#symfoware.thriftから生成したモジュール
import sys
sys.path.append('./gen-py')
from symfoware.voldemort.ttypes import ThriftData

if __name__ == '__main__':
    
    logging.basicConfig(level=logging.INFO,)
    
    #StoreClientを生成
    s = StoreClient('test', [('192.168.1.250', 6666)])
    
    #Javaで登録したデータを検索
    r = s.get("key")[0]
    
    #値を取得
    value = r[0]
    version =r[1]
    
    #thriftオブジェクトへの変換準備
    buf = TTransport.TMemoryBuffer(value)
    protocol = TBinaryProtocol.TBinaryProtocol(buf)
    
    #readメソッドでオブジェクトの内容を復元
    td = ThriftData()
    td.read(protocol)
    
    #取得した値を表示
    print '[[value]]'
    print unicode(td.title, 'utf-8')
    print unicode(td.details, 'utf-8')
    
    for v in td.list_sample:
        print unicode(v, 'utf-8')





TTransport.TMemoryBufferにVoldemortで取得したデータをぶち込み、
ThriftData().read()でオブジェクトに反映させます。


実行してみると・・・


C:\src\python\voldemort>python test.py
[[value]]
日本語タイトルを設定
日本語の詳細を設定してみます。
その1
その2
その3



上手く読み込めました。






テーマ:データベース - ジャンル:コンピュータ

  1. 2010/04/25(日) 12:11:43|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Debian + VoldemortにWindows + Pythonで接続する

Debianで動かしているVoldemortに、Windows + Pythonで接続してみようと思います。

Voldemortを解凍したフォルダ
%Voldemort%/clients/python
ここにサンプルがありましたので、これを参考にプログラムを書いてみます。



PythonからProtocol Buffersを使用する



Voldemortの通信は、Protocol Buffersを使用しているようです。
まずは、Protocol Buffersのインストールを行います。


Protocol Buffersのページ
Protocol Buffers

ダウンロードページ
http://code.google.com/p/protobuf/downloads/list
ここから、
protoc-2.3.0-win32.zip
protobuf-2.3.0.zip
の二つをダウンロードします。



protoc-2.3.0-win32.zipを解凍すると、protoc.exeが入っていると思います。
protobuf-2.3.0.zipを解凍したフォルダの中に、javaやpythonといったフォルダが
作成されると思います。
同じ階層にsrcというフォルダが出来ますので、この中に先ほどのprotoc.exeを
コピーしておきます。


コマンドプロンプトを開き、protobuf-2.3.0.zipを解凍したフォルダのpythonに移動。
以下のコマンドを実行すると、protobufがインストールできます。


C:\protobuf-2.3.0\python>python setup.py install




これで、PythonでProtocol Buffersが使用できるようになりました。





store.xml



Debianで動いているVoldemortの設定ファイルを書き換えます。

%Voldemort%/config/single_node_cluster/config/stores.xml
このファイルを、以下のように設定しました。



<stores>
    <store>
        <name>test</name>
        <persistence>bdb</persistence>
        <routing>client</routing>
        <replication-factor>1</replication-factor>
        <required-reads>1</required-reads>
        <required-writes>1</required-writes>
        <key-serializer>
            <type>string</type>
        </key-serializer>
        <value-serializer>
            <type>string</type>
        </value-serializer>
    </store>
</stores>



ファイルを変更したら、Voldemortを再起動します。




サンプルプログラム




Voldemortを解凍したフォルダ
%Voldemort%/clients/python
ここにある


voldemort.py
voldemort_client_pb2.py



この2つのファイルを、これから作成するサンプルプログラムの
ソースと同じ場所にコピーしておきます。


原因不明ですが、voldemort.pyのエラーチェック部分でこんな
エラーが発生します。


C:\src\python\voldemort>python test.py
Traceback (most recent call last):
File "test.py", line 12, in <module>
    s = StoreClient('test', [('192.168.1.250', 6666)])
File "C:\src\python\voldemort\voldemort.py", line 100, in __init__
    self.nodes = self._bootstrap_metadata(bootstrap_urls)
File "C:\src\python\voldemort\voldemort.py", line 188, in _bootstrap_metad
ata
    cluster_xmls = self._get_with_connection(connection, 'metadata', 'cluster.xm
l', should_route = False)
File "C:\src\python\voldemort\voldemort.py", line 274, in _get_with_connec
tion
    self._check_error(resp)
File "C:\src\python\voldemort\voldemort.py", line 206, in _check_error
    if resp._has_error:
AttributeError: 'GetResponse' object has no attribute '_has_error'




コピーしたvoldemort.pyの206行目付近をコメントして逃げました。


    ## check if the server response has an error, if so throw an exception
    def _check_error(self, resp):
        #エラーが発生するのでコメントアウト
        """
        if resp._has_error:
            raise VoldemortException(resp.error.error_message, resp.error.error_code)
        """
        pass






作成したサンプルはこちらになります。


■test.py


# -*- coding:utf-8 -*-

import logging
import time
from voldemort import StoreClient

if __name__ == '__main__':
    
    logging.basicConfig(level=logging.INFO,)
    
    #StoreClientを生成
    s = StoreClient('test', [('192.168.1.250', 6666)])
    
    #データの登録
    s.put("key", u"日本語通るかな?".encode("utf-8"))
    
    #登録したデータを検索
    # [(値, versionオブジェクト)]
    #形式で検索結果が帰ってくる
    r = s.get("key")
    
    value = s.get("key")[0][0]
    version = s.get("key")[0][1]
    
    print '[[value]]'
    print unicode(value, "utf-8")
    
    print ''
    print '[[version]]'
    print version






実行してみると・・・


C:\src\python\voldemort>python test.py
[[value]]
日本語通るかな?

[[version]]
entries {
  node_id: 0
  version: 1
}
timestamp: 1271321195277




ちゃんと登録できました。



テーマ:データベース - ジャンル:コンピュータ

  1. 2010/04/24(土) 12:09:30|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Voldemortのデータにオブジェクトを登録する方法(thrift使用)

Java標準のシリアライズ機能を使用してオブジェクトを変換。
Voldemortのデータとして登録することに成功しました。
Voldemortのデータにオブジェクトを登録する方法(java-serialization使用)


ドキュメントを見てみると、以下のデータ型が使用可能のようです。

json,
java-serialization
string
protobuff
thrift
identity (meaning raw bytes)




stringとjava-serializationは試しましたので、
Debianで動作しているVoldemortをWindows + Javaで操作する
Voldemortのデータにオブジェクトを登録する方法(java-serialization使用)
thriftを使用してみます。





Thriftのインストール



Thriftとは、データ型や関数を定義したファイルをテンプレートとし、
各種言語に適したソースコードに変換してくれるツールです。

以前、Debianにインストールしたときの記事はこちら。
DebianにApache Thriftをインストールする


なお、Thriftは雛形からjavaのソースに変換するだけなので、
Voldemortが動作しているサーバーにインストールする必要はありません。





Thriftの定義体とjavaソースの生成



サンプルとして、こんな定義体を考えました。

■voldemort.thrift


namespace java com.fc2.blog68.symfoware.voldemort

struct ThriftData {
    1:string title,
    2:string details,
    3:list<string> list_sample,
}




titleとdetailsの2つの文字列型とlist_sampleという文字列のリスト型を
保持するThriftDataという構造体を定義します。


javaのソースを得るには、以下のコマンドを実行します。


# thrift --gen java voldemort.thrift




すると、gen-javaというディレクトリが生成されます。
こんな感じで、ソースが出来ます。

gen-java/com/fc2/blog68/symfoware/voldemort/ThriftData.java






Thriftにより生成されたソースです。

■ThriftData.java


/**
* Autogenerated by Thrift
*
* DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
*/
package com.fc2.blog68.symfoware.voldemort;

import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import java.util.EnumMap;
import java.util.Set;
import java.util.HashSet;
import java.util.EnumSet;
import java.util.Collections;
import java.util.BitSet;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.thrift.*;
import org.apache.thrift.meta_data.*;
import org.apache.thrift.protocol.*;

public class ThriftData implements TBase<ThriftData._Fields>, java.io.Serializable, Cloneable, Comparable<ThriftData> {
  private static final TStruct STRUCT_DESC = new TStruct("ThriftData");

  private static final TField TITLE_FIELD_DESC = new TField("title", TType.STRING, (short)1);
  private static final TField DETAILS_FIELD_DESC = new TField("details", TType.STRING, (short)2);
  private static final TField LIST_SAMPLE_FIELD_DESC = new TField("list_sample", TType.LIST, (short)3);

  public String title;
  public String details;
  public List<String> list_sample;

  /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
  public enum _Fields implements TFieldIdEnum {
    TITLE((short)1, "title"),
    DETAILS((short)2, "details"),
    LIST_SAMPLE((short)3, "list_sample");

    private static final Map<Integer, _Fields> byId = new HashMap<Integer, _Fields>();
    private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();

    static {
      for (_Fields field : EnumSet.allOf(_Fields.class)) {
        byId.put((int)field._thriftId, field);
        byName.put(field.getFieldName(), field);
      }
    }

    /**
     * Find the _Fields constant that matches fieldId, or null if its not found.
     */
    public static _Fields findByThriftId(int fieldId) {
      return byId.get(fieldId);
    }

    /**
     * Find the _Fields constant that matches fieldId, throwing an exception
     * if it is not found.
     */
    public static _Fields findByThriftIdOrThrow(int fieldId) {
      _Fields fields = findByThriftId(fieldId);
      if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
      return fields;
    }

    /**
     * Find the _Fields constant that matches name, or null if its not found.
     */
    public static _Fields findByName(String name) {
      return byName.get(name);
    }

    private final short _thriftId;
    private final String _fieldName;

    _Fields(short thriftId, String fieldName) {
      _thriftId = thriftId;
      _fieldName = fieldName;
    }

    public short getThriftFieldId() {
      return _thriftId;
    }

    public String getFieldName() {
      return _fieldName;
    }
  }

  // isset id assignments

  public static final Map<_Fields, FieldMetaData> metaDataMap = Collections.unmodifiableMap(new EnumMap<_Fields, FieldMetaData>(_Fields.class) {{
    put(_Fields.TITLE, new FieldMetaData("title", TFieldRequirementType.DEFAULT,
        new FieldValueMetaData(TType.STRING)));
    put(_Fields.DETAILS, new FieldMetaData("details", TFieldRequirementType.DEFAULT,
        new FieldValueMetaData(TType.STRING)));
    put(_Fields.LIST_SAMPLE, new FieldMetaData("list_sample", TFieldRequirementType.DEFAULT,
        new ListMetaData(TType.LIST,
            new FieldValueMetaData(TType.STRING))));
  }});

  static {
    FieldMetaData.addStructMetaDataMap(ThriftData.class, metaDataMap);
  }

  public ThriftData() {
  }

  public ThriftData(
    String title,
    String details,
    List<String> list_sample)
  {
    this();
    this.title = title;
    this.details = details;
    this.list_sample = list_sample;
  }

  /**
   * Performs a deep copy on <i>other</i>.
   */
  public ThriftData(ThriftData other) {
    if (other.isSetTitle()) {
      this.title = other.title;
    }
    if (other.isSetDetails()) {
      this.details = other.details;
    }
    if (other.isSetList_sample()) {
      List<String> __this__list_sample = new ArrayList<String>();
      for (String other_element : other.list_sample) {
        __this__list_sample.add(other_element);
      }
      this.list_sample = __this__list_sample;
    }
  }

  public ThriftData deepCopy() {
    return new ThriftData(this);
  }

  @Deprecated
  public ThriftData clone() {
    return new ThriftData(this);
  }

  public String getTitle() {
    return this.title;
  }

  public ThriftData setTitle(String title) {
    this.title = title;
    return this;
  }

  public void unsetTitle() {
    this.title = null;
  }

  /** Returns true if field title is set (has been asigned a value) and false otherwise */
  public boolean isSetTitle() {
    return this.title != null;
  }

  public void setTitleIsSet(boolean value) {
    if (!value) {
      this.title = null;
    }
  }

  public String getDetails() {
    return this.details;
  }

  public ThriftData setDetails(String details) {
    this.details = details;
    return this;
  }

  public void unsetDetails() {
    this.details = null;
  }

  /** Returns true if field details is set (has been asigned a value) and false otherwise */
  public boolean isSetDetails() {
    return this.details != null;
  }

  public void setDetailsIsSet(boolean value) {
    if (!value) {
      this.details = null;
    }
  }

  public int getList_sampleSize() {
    return (this.list_sample == null) ? 0 : this.list_sample.size();
  }

  public java.util.Iterator<String> getList_sampleIterator() {
    return (this.list_sample == null) ? null : this.list_sample.iterator();
  }

  public void addToList_sample(String elem) {
    if (this.list_sample == null) {
      this.list_sample = new ArrayList<String>();
    }
    this.list_sample.add(elem);
  }

  public List<String> getList_sample() {
    return this.list_sample;
  }

  public ThriftData setList_sample(List<String> list_sample) {
    this.list_sample = list_sample;
    return this;
  }

  public void unsetList_sample() {
    this.list_sample = null;
  }

  /** Returns true if field list_sample is set (has been asigned a value) and false otherwise */
  public boolean isSetList_sample() {
    return this.list_sample != null;
  }

  public void setList_sampleIsSet(boolean value) {
    if (!value) {
      this.list_sample = null;
    }
  }

  public void setFieldValue(_Fields field, Object value) {
    switch (field) {
    case TITLE:
      if (value == null) {
        unsetTitle();
      } else {
        setTitle((String)value);
      }
      break;

    case DETAILS:
      if (value == null) {
        unsetDetails();
      } else {
        setDetails((String)value);
      }
      break;

    case LIST_SAMPLE:
      if (value == null) {
        unsetList_sample();
      } else {
        setList_sample((List<String>)value);
      }
      break;

    }
  }

  public void setFieldValue(int fieldID, Object value) {
    setFieldValue(_Fields.findByThriftIdOrThrow(fieldID), value);
  }

  public Object getFieldValue(_Fields field) {
    switch (field) {
    case TITLE:
      return getTitle();

    case DETAILS:
      return getDetails();

    case LIST_SAMPLE:
      return getList_sample();

    }
    throw new IllegalStateException();
  }

  public Object getFieldValue(int fieldId) {
    return getFieldValue(_Fields.findByThriftIdOrThrow(fieldId));
  }

  /** Returns true if field corresponding to fieldID is set (has been asigned a value) and false otherwise */
  public boolean isSet(_Fields field) {
    switch (field) {
    case TITLE:
      return isSetTitle();
    case DETAILS:
      return isSetDetails();
    case LIST_SAMPLE:
      return isSetList_sample();
    }
    throw new IllegalStateException();
  }

  public boolean isSet(int fieldID) {
    return isSet(_Fields.findByThriftIdOrThrow(fieldID));
  }

  @Override
  public boolean equals(Object that) {
    if (that == null)
      return false;
    if (that instanceof ThriftData)
      return this.equals((ThriftData)that);
    return false;
  }

  public boolean equals(ThriftData that) {
    if (that == null)
      return false;

    boolean this_present_title = true && this.isSetTitle();
    boolean that_present_title = true && that.isSetTitle();
    if (this_present_title || that_present_title) {
      if (!(this_present_title && that_present_title))
        return false;
      if (!this.title.equals(that.title))
        return false;
    }

    boolean this_present_details = true && this.isSetDetails();
    boolean that_present_details = true && that.isSetDetails();
    if (this_present_details || that_present_details) {
      if (!(this_present_details && that_present_details))
        return false;
      if (!this.details.equals(that.details))
        return false;
    }

    boolean this_present_list_sample = true && this.isSetList_sample();
    boolean that_present_list_sample = true && that.isSetList_sample();
    if (this_present_list_sample || that_present_list_sample) {
      if (!(this_present_list_sample && that_present_list_sample))
        return false;
      if (!this.list_sample.equals(that.list_sample))
        return false;
    }

    return true;
  }

  @Override
  public int hashCode() {
    return 0;
  }

  public int compareTo(ThriftData other) {
    if (!getClass().equals(other.getClass())) {
      return getClass().getName().compareTo(other.getClass().getName());
    }

    int lastComparison = 0;
    ThriftData typedOther = (ThriftData)other;

    lastComparison = Boolean.valueOf(isSetTitle()).compareTo(isSetTitle());
    if (lastComparison != 0) {
      return lastComparison;
    }
    lastComparison = TBaseHelper.compareTo(title, typedOther.title);
    if (lastComparison != 0) {
      return lastComparison;
    }
    lastComparison = Boolean.valueOf(isSetDetails()).compareTo(isSetDetails());
    if (lastComparison != 0) {
      return lastComparison;
    }
    lastComparison = TBaseHelper.compareTo(details, typedOther.details);
    if (lastComparison != 0) {
      return lastComparison;
    }
    lastComparison = Boolean.valueOf(isSetList_sample()).compareTo(isSetList_sample());
    if (lastComparison != 0) {
      return lastComparison;
    }
    lastComparison = TBaseHelper.compareTo(list_sample, typedOther.list_sample);
    if (lastComparison != 0) {
      return lastComparison;
    }
    return 0;
  }

  public void read(TProtocol iprot) throws TException {
    TField field;
    iprot.readStructBegin();
    while (true)
    {
      field = iprot.readFieldBegin();
      if (field.type == TType.STOP) {
        break;
      }
      _Fields fieldId = _Fields.findByThriftId(field.id);
      if (fieldId == null) {
        TProtocolUtil.skip(iprot, field.type);
      } else {
        switch (fieldId) {
          case TITLE:
            if (field.type == TType.STRING) {
              this.title = iprot.readString();
            } else {
              TProtocolUtil.skip(iprot, field.type);
            }
            break;
          case DETAILS:
            if (field.type == TType.STRING) {
              this.details = iprot.readString();
            } else {
              TProtocolUtil.skip(iprot, field.type);
            }
            break;
          case LIST_SAMPLE:
            if (field.type == TType.LIST) {
              {
                TList _list0 = iprot.readListBegin();
                this.list_sample = new ArrayList<String>(_list0.size);
                for (int _i1 = 0; _i1 < _list0.size; ++_i1)
                {
                  String _elem2;
                  _elem2 = iprot.readString();
                  this.list_sample.add(_elem2);
                }
                iprot.readListEnd();
              }
            } else {
              TProtocolUtil.skip(iprot, field.type);
            }
            break;
        }
        iprot.readFieldEnd();
      }
    }
    iprot.readStructEnd();

    // check for required fields of primitive type, which can't be checked in the validate method
    validate();
  }

  public void write(TProtocol oprot) throws TException {
    validate();

    oprot.writeStructBegin(STRUCT_DESC);
    if (this.title != null) {
      oprot.writeFieldBegin(TITLE_FIELD_DESC);
      oprot.writeString(this.title);
      oprot.writeFieldEnd();
    }
    if (this.details != null) {
      oprot.writeFieldBegin(DETAILS_FIELD_DESC);
      oprot.writeString(this.details);
      oprot.writeFieldEnd();
    }
    if (this.list_sample != null) {
      oprot.writeFieldBegin(LIST_SAMPLE_FIELD_DESC);
      {
        oprot.writeListBegin(new TList(TType.STRING, this.list_sample.size()));
        for (String _iter3 : this.list_sample)
        {
          oprot.writeString(_iter3);
        }
        oprot.writeListEnd();
      }
      oprot.writeFieldEnd();
    }
    oprot.writeFieldStop();
    oprot.writeStructEnd();
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder("ThriftData(");
    boolean first = true;

    sb.append("title:");
    if (this.title == null) {
      sb.append("null");
    } else {
      sb.append(this.title);
    }
    first = false;
    if (!first) sb.append(", ");
    sb.append("details:");
    if (this.details == null) {
      sb.append("null");
    } else {
      sb.append(this.details);
    }
    first = false;
    if (!first) sb.append(", ");
    sb.append("list_sample:");
    if (this.list_sample == null) {
      sb.append("null");
    } else {
      sb.append(this.list_sample);
    }
    first = false;
    sb.append(")");
    return sb.toString();
  }

  public void validate() throws TException {
    // check for required fields
  }

}




このソースを開発環境にコピーしておきます。





Voldemortのstores.xmlを編集



作成したThriftDataをserializerとして指定します。

%Voldemort%/config/single_node_cluster/config/stores.xml
を開いて、以下のように編集しました。


<stores>
  <store>
    <name>test</name>
    <persistence>bdb</persistence>
    <routing>client</routing>
    <replication-factor>1</replication-factor>
    <required-reads>1</required-reads>
    <required-writes>1</required-writes>
    <key-serializer>
      <type>string</type>
    </key-serializer>
    <value-serializer>
      <type>thrift</type>
      <schema-info>java=com.fc2.blog68.symfoware.voldemort.ThriftData,protocol=binary</schema-info>
    </value-serializer>
  </store>
</stores>




value-serializerのtypeに「thrift」
schema-infoに「java=com.fc2.blog68.symfoware.voldemort.ThriftData,protocol=binary」
と、作成したクラス名を指定します。

Voldemortが指定したcom.fc2.blog68.symfoware.voldemort.ThriftDataのクラスを
ロードしている必要があるのかな?と思っていましたが、単純にクラス名を
管理しているだけのようで、クラスファイルのコピーは不要でした。


編集が終わったら、Voldemortを再起動します。





開発環境にビルドパスを追加



Voldemort側の設定は終わりましたので、今度は開発環境の設定です。
serializerにthriftを使用するため、jarファイルをビルドパスに追加します。


追加するjarファイルは以下の3つ。


libthrift-0.2.0.jar
slf4j-api-1.5.6.jar
slf4j-log4j12-1.5.6.jar



これらのjarは、Voldemort/libにあるはずです。


最終的に、使用するjarファイルは以下の7つになります。


voldemort-0.80.1.jar
google-collect-1.0.jar
jdom-1.1.jar
log4j-1.2.15.jar
libthrift-0.2.0.jar
slf4j-api-1.5.6.jar
slf4j-log4j12-1.5.6.jar







サンプルプログラム



サンプルを作成し、動かしてみました。

■Sample.java


package com.fc2.blog68.symfoware.voldemort;

import java.util.ArrayList;
import java.util.List;

import voldemort.client.ClientConfig;
import voldemort.client.SocketStoreClientFactory;
import voldemort.client.StoreClient;
import voldemort.client.StoreClientFactory;

public class Sample {
    public static void main(String[] args) {
        
        String[] bootstrapUrls = new String[]{"tcp://192.168.1.250:6666"};
        
        ClientConfig cc = new ClientConfig();
        cc.setBootstrapUrls(bootstrapUrls);
        
        StoreClientFactory factory = new SocketStoreClientFactory(cc);
        
        //最初にキーの型、二番目に登録するデータの型を定義する
        StoreClient<String, ThriftData> client = factory.getStoreClient("test");
        
        client.delete("key");
        
        //登録用のオブジェクトを生成
        ThriftData data = new ThriftData();
        data.title = "日本語タイトルを設定";
        data.details = "日本語の詳細を設定してみます。";
        
        List<String> list = new ArrayList<String>();
        list.add("その1");
        list.add("その2");
        list.add("その3");
        data.list_sample = list;
        
        client.put("key", data);
        
        
        data = client.getValue("key");
        System.out.println(data.getTitle());
        System.out.println(data.getDetails());
        
        for (int i = 0; i < data.getList_sampleSize(); i++) {
            System.out.println(data.getList_sample().get(i));
        }
        
    }
}




動かしてみると・・・



[2010-04-18 15:38:01,821 voldemort.client.DefaultStoreClient] INFO bootstrapping metadata.
日本語タイトルを設定
日本語の詳細を設定してみます。
その1
その2
その3



狙い通りの動作になっています。




テーマ:データベース - ジャンル:コンピュータ

  1. 2010/04/23(金) 12:11:55|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
次のページ