(empty log message)
@@ -0,0 +1,33 @@ | ||
1 | +package okuyama.imdst.client; | |
2 | + | |
3 | +/** | |
4 | + * OkuyamaClientが一度のリクエストでは取得しきれないような<br> | |
5 | + * 大量のデータを扱う場合に利用するResultSetクラス.<br> | |
6 | + * 以下のような構文にてデータを取得する | |
7 | + * 以下は、Tagを利用して全ての紐付くKeyとValueを出力している | |
8 | + * ----------------------------------------------------------------- | |
9 | + * OkuyamaResultSet resultSet = client.getTagKeyResult(tagStr); | |
10 | + * | |
11 | + * while(resultSet.next()) { | |
12 | + * System.out.println("Key=" + (Object)resultSet.getKey()); | |
13 | + * System.out.println("Value=" + (Object)resultSet.getValue()); | |
14 | + * } | |
15 | + * resultSet.close(); | |
16 | + * ------------------------------------------------------------------ | |
17 | + * | |
18 | + * | |
19 | + * @author T.Okuyama | |
20 | + * @license GPL(Lv3) | |
21 | + */ | |
22 | +public interface OkuyamaResultSet { | |
23 | + | |
24 | + public boolean next() throws OkuyamaClientException; | |
25 | + | |
26 | + public Object getKey() throws OkuyamaClientException; | |
27 | + | |
28 | + public Object getValue() throws OkuyamaClientException; | |
29 | + | |
30 | + public void close() throws OkuyamaClientException; | |
31 | + | |
32 | + public boolean isClose() throws OkuyamaClientException; | |
33 | +} | |
\ No newline at end of file |
@@ -12,6 +12,7 @@ | ||
12 | 12 | import okuyama.imdst.util.ImdstDefine; |
13 | 13 | import okuyama.imdst.util.SystemUtil; |
14 | 14 | import okuyama.imdst.client.io.*; |
15 | +import okuyama.imdst.client.result.*; | |
15 | 16 | |
16 | 17 | /** |
17 | 18 | * MasterNodeと通信を行うクライアント<br> |
@@ -160,6 +161,17 @@ | ||
160 | 161 | // 接続中のokuyamaのバージョンNo |
161 | 162 | protected double okuyamaVersionNo = 0; |
162 | 163 | |
164 | + protected boolean useAutoConnect = false; | |
165 | + | |
166 | + // コネクション構築に用いた変数を格納 | |
167 | + protected String[] initParamMasterNodes = null; | |
168 | + protected String initParamServer = null; | |
169 | + protected int initParamPort = -1; | |
170 | + protected String initParamEncoding = null; | |
171 | + protected int initParamOpenTimeout = -1; | |
172 | + protected int initParamConnectionTimeout = -1; | |
173 | + | |
174 | + | |
163 | 175 | // サーバへの出力用 |
164 | 176 | protected PrintWriter pw = null; |
165 | 177 |
@@ -257,6 +269,8 @@ | ||
257 | 269 | * @param masterNodes 接続情報の配列 "IP:PORT"の形式 |
258 | 270 | */ |
259 | 271 | public void setConnectionInfos(String[] masterNodes) { |
272 | + this.initParamMasterNodes = masterNodes; | |
273 | + | |
260 | 274 | this.masterNodesList = new ArrayList(masterNodes.length); |
261 | 275 | for (int i = 0; i < masterNodes.length; i++) { |
262 | 276 | this.masterNodesList.add(masterNodes[i]); |
@@ -271,6 +285,7 @@ | ||
271 | 285 | * @throws OkuyamaClientException |
272 | 286 | */ |
273 | 287 | public void autoConnect() throws OkuyamaClientException { |
288 | + this.useAutoConnect = true; | |
274 | 289 | ArrayList tmpMasterNodeList = new ArrayList(); |
275 | 290 | ArrayList workList = (ArrayList)this.masterNodesList.clone(); |
276 | 291 | Random rnd = new Random(); |
@@ -366,6 +381,13 @@ | ||
366 | 381 | * @throws OkuyamaClientException |
367 | 382 | */ |
368 | 383 | public void connect(String server, int port, String encoding, int openTimeout, int connectionTimeout) throws OkuyamaClientException { |
384 | + this.initParamServer = server; | |
385 | + this.initParamPort = port; | |
386 | + this.initParamEncoding = encoding; | |
387 | + this.initParamOpenTimeout = openTimeout; | |
388 | + this.initParamConnectionTimeout = connectionTimeout; | |
389 | + this.useAutoConnect = false; | |
390 | + | |
369 | 391 | try { |
370 | 392 | this.socket = new Socket(); |
371 | 393 | InetSocketAddress inetAddr = new InetSocketAddress(server, port); |
@@ -5826,7 +5848,293 @@ | ||
5826 | 5848 | } |
5827 | 5849 | |
5828 | 5850 | |
5851 | + | |
5829 | 5852 | /** |
5853 | + * MasterNodeからTagを指定することで紐付くKeyとValueが取得可能な、OkuyamaResultSetを取得する.<br> | |
5854 | + * Tagは打たれているが実際は既に存在しないValueが紐付くKey値は取得出来ない.<br> | |
5855 | + * | |
5856 | + * @param tagStr Tag値 | |
5857 | + * @return OkuyamaResultSet 結果のOkuyamaResultSet Tagがそもそも存在しない場合はnullが返る | |
5858 | + * @throws OkuyamaClientException | |
5859 | + */ | |
5860 | + public OkuyamaResultSet getTagKeyResult(String tagStr) throws OkuyamaClientException { | |
5861 | + return this.getTagKeyResult(tagStr, null); | |
5862 | + } | |
5863 | + | |
5864 | + | |
5865 | + /** | |
5866 | + * MasterNodeからTagを指定することで紐付くKeyとValueが取得可能な、OkuyamaResultSetを取得する.<br> | |
5867 | + * Tagは打たれているが実際は既に存在しないValueが紐付くKey値は取得出来ない.<br> | |
5868 | + * | |
5869 | + * @param tagStr Tag値 | |
5870 | + * @param encoding エンコーディング指定 | |
5871 | + * @return OkuyamaResultSet 結果のOkuyamaResultSet Tagがそもそも存在しない場合はnullが返る | |
5872 | + * @throws OkuyamaClientException | |
5873 | + */ | |
5874 | + public OkuyamaResultSet getTagKeyResult(String tagStr, String encoding) throws OkuyamaClientException { | |
5875 | + OkuyamaResultSet okuyamaResultSet = null; | |
5876 | + String serverRetStr = null; | |
5877 | + String[] serverRet = null; | |
5878 | + | |
5879 | + StringBuilder serverRequestBuf = null; | |
5880 | + | |
5881 | + try { | |
5882 | + if (this.socket == null) throw new OkuyamaClientException("No ServerConnect!!"); | |
5883 | + | |
5884 | + if (0.90 > this.okuyamaVersionNo) { | |
5885 | + throw new OkuyamaClientException("The version of the server is old [The 'searchValue' method can be used since version 0.9.0]"); | |
5886 | + } | |
5887 | + | |
5888 | + if (encoding == null) encoding = platformDefaultEncoding; | |
5889 | + | |
5890 | + // エラーチェック | |
5891 | + // Keyに対する無指定チェック | |
5892 | + if (tagStr == null || tagStr.equals("")) { | |
5893 | + throw new OkuyamaClientException("The blank is not admitted on a tag"); | |
5894 | + } | |
5895 | + | |
5896 | + // Tagに対するLengthチェック | |
5897 | + if (tagStr.getBytes().length > maxKeySize) throw new OkuyamaClientException("Save Tag Max Size " + maxKeySize + " Byte"); | |
5898 | + | |
5899 | + // 文字列バッファ初期化 | |
5900 | + serverRequestBuf = new StringBuilder(ImdstDefine.stringBufferSmallSize); | |
5901 | + | |
5902 | + | |
5903 | + // 処理番号連結 | |
5904 | + serverRequestBuf.append("45"); | |
5905 | + // セパレータ連結 | |
5906 | + serverRequestBuf.append(OkuyamaClient.sepStr); | |
5907 | + | |
5908 | + // tag値連結(Keyはデータ送信時には必ず文字列が必要) | |
5909 | + serverRequestBuf.append(new String(this.dataEncoding(tagStr.getBytes()))); | |
5910 | + | |
5911 | + | |
5912 | + // サーバ送信 | |
5913 | + pw.println(serverRequestBuf.toString()); | |
5914 | + pw.flush(); | |
5915 | + | |
5916 | + // サーバから結果受け取り | |
5917 | + serverRetStr = br.readLine(); | |
5918 | + serverRet = serverRetStr.split(OkuyamaClient.sepStr); | |
5919 | + | |
5920 | + | |
5921 | + // 処理の妥当性確 | |
5922 | + if (serverRet[0].equals("45")) { | |
5923 | + if (serverRet[1].equals("true")) { | |
5924 | + | |
5925 | + // データ有り | |
5926 | + String indexListStr= serverRet[2]; | |
5927 | + | |
5928 | + if (indexListStr.trim().equals("")) { | |
5929 | + | |
5930 | + okuyamaResultSet = null; | |
5931 | + } else { | |
5932 | + | |
5933 | + String[] indexList = indexListStr.split(ImdstDefine.imdstTagKeyAppendSep); | |
5934 | + OkuyamaClient retSetClient = new OkuyamaClient(maxKeySize); | |
5935 | + if (this.useAutoConnect) { | |
5936 | + retSetClient.setConnectionInfos(this.initParamMasterNodes); | |
5937 | + retSetClient.autoConnect(); | |
5938 | + } else { | |
5939 | + retSetClient.connect(this.initParamServer, this.initParamPort, this.initParamEncoding, this.initParamOpenTimeout, this.initParamConnectionTimeout); | |
5940 | + } | |
5941 | + okuyamaResultSet = new OkuyamaTagKeysResultSet(retSetClient, tagStr, indexList, encoding); | |
5942 | + } | |
5943 | + } else if(serverRet[1].equals("false")) { | |
5944 | + | |
5945 | + // データなし | |
5946 | + okuyamaResultSet = null; | |
5947 | + } else if(serverRet[1].equals("error")) { | |
5948 | + | |
5949 | + // エラー発生 | |
5950 | + okuyamaResultSet = null; | |
5951 | + } | |
5952 | + } else { | |
5953 | + | |
5954 | + // 妥当性違反 | |
5955 | + throw new OkuyamaClientException("Execute Violation of validity [" + serverRet[0] + "]"); | |
5956 | + } | |
5957 | + } catch (OkuyamaClientException ice) { | |
5958 | + throw ice; | |
5959 | + } catch (ConnectException ce) { | |
5960 | + if (this.masterNodesList != null && masterNodesList.size() > 1) { | |
5961 | + try { | |
5962 | + this.autoConnect(); | |
5963 | + okuyamaResultSet = this.getTagKeyResult(tagStr, encoding); | |
5964 | + } catch (Exception e) { | |
5965 | + throw new OkuyamaClientException(ce); | |
5966 | + } | |
5967 | + } else { | |
5968 | + throw new OkuyamaClientException(ce); | |
5969 | + } | |
5970 | + } catch (SocketException se) { | |
5971 | + if (this.masterNodesList != null && masterNodesList.size() > 1) { | |
5972 | + try { | |
5973 | + this.autoConnect(); | |
5974 | + okuyamaResultSet = this.getTagKeyResult(tagStr, encoding); | |
5975 | + } catch (Exception e) { | |
5976 | + throw new OkuyamaClientException(se); | |
5977 | + } | |
5978 | + } else { | |
5979 | + throw new OkuyamaClientException(se); | |
5980 | + } | |
5981 | + } catch (Throwable e) { | |
5982 | + if (this.masterNodesList != null && masterNodesList.size() > 1) { | |
5983 | + try { | |
5984 | + this.autoConnect(); | |
5985 | + okuyamaResultSet = this.getTagKeyResult(tagStr, encoding); | |
5986 | + } catch (Exception ee) { | |
5987 | + throw new OkuyamaClientException(e); | |
5988 | + } | |
5989 | + } else { | |
5990 | + throw new OkuyamaClientException(e); | |
5991 | + } | |
5992 | + } | |
5993 | + return okuyamaResultSet; | |
5994 | + } | |
5995 | + | |
5996 | + | |
5997 | + /** | |
5998 | + * MasterNodeからTagとKey格納bucketのIndexを使用してKey値配列を取得する.<br> | |
5999 | + * 本メソッドは、OkuyamaTagKeysResultSetクラスからの利用を想定して作成されているため、 | |
6000 | + * それ以外の部分からの呼び出しは推奨しない.<br> | |
6001 | + * | |
6002 | + * @param tagStr Tag値 | |
6003 | + * @param index bucketIndex | |
6004 | + * @return Object[] 要素1(データ有無):"true" or "false",要素2(Key値配列):Stringの配列 | |
6005 | + * @throws OkuyamaClientException | |
6006 | + */ | |
6007 | + public Object[] getTargetIndexTagKeys(String tagStr, String bucketIndex) throws OkuyamaClientException { | |
6008 | + Object[] ret = new Object[2]; | |
6009 | + String serverRetStr = null; | |
6010 | + String[] serverRet = null; | |
6011 | + | |
6012 | + StringBuilder serverRequestBuf = null; | |
6013 | + | |
6014 | + try { | |
6015 | + if (this.socket == null) throw new OkuyamaClientException("No ServerConnect!!"); | |
6016 | + | |
6017 | + if (0.90 > this.okuyamaVersionNo) { | |
6018 | + throw new OkuyamaClientException("The version of the server is old [The 'searchValue' method can be used since version 0.9.0]"); | |
6019 | + } | |
6020 | + | |
6021 | + // エラーチェック | |
6022 | + // Keyに対する無指定チェック | |
6023 | + if (tagStr == null || tagStr.equals("")) { | |
6024 | + throw new OkuyamaClientException("The blank is not admitted on a tag"); | |
6025 | + } | |
6026 | + | |
6027 | + // Tagに対するLengthチェック | |
6028 | + if (tagStr.getBytes().length > maxKeySize) throw new OkuyamaClientException("Save Tag Max Size " + maxKeySize + " Byte"); | |
6029 | + | |
6030 | + // 文字列バッファ初期化 | |
6031 | + serverRequestBuf = new StringBuilder(ImdstDefine.stringBufferSmallSize); | |
6032 | + | |
6033 | + | |
6034 | + // 処理番号連結 | |
6035 | + serverRequestBuf.append("46"); | |
6036 | + // セパレータ連結 | |
6037 | + serverRequestBuf.append(OkuyamaClient.sepStr); | |
6038 | + | |
6039 | + | |
6040 | + // tag値連結(Keyはデータ送信時には必ず文字列が必要) | |
6041 | + serverRequestBuf.append(new String(this.dataEncoding(tagStr.getBytes()))); | |
6042 | + // セパレータ連結 | |
6043 | + serverRequestBuf.append(OkuyamaClient.sepStr); | |
6044 | + | |
6045 | + // bucketインデックス | |
6046 | + serverRequestBuf.append(bucketIndex); | |
6047 | + | |
6048 | + | |
6049 | + // サーバ送信 | |
6050 | + pw.println(serverRequestBuf.toString()); | |
6051 | + pw.flush(); | |
6052 | + | |
6053 | + // サーバから結果受け取り | |
6054 | + serverRetStr = br.readLine(); | |
6055 | + serverRet = serverRetStr.split(OkuyamaClient.sepStr); | |
6056 | + | |
6057 | + // 処理の妥当性確 | |
6058 | + if (serverRet[0].equals("46")) { | |
6059 | + if (serverRet[1].equals("true")) { | |
6060 | + | |
6061 | + // データ有り | |
6062 | + ret[0] = serverRet[1]; | |
6063 | + | |
6064 | + // Valueがブランク文字か調べる | |
6065 | + if (serverRet[2].equals("")) { | |
6066 | + String[] tags = {""}; | |
6067 | + ret[1] = tags; | |
6068 | + } else { | |
6069 | + String[] tags = null; | |
6070 | + String[] cnvTags = null; | |
6071 | + | |
6072 | + tags = serverRet[2].split(tagKeySep); | |
6073 | + String[] decTags = new String[tags.length]; | |
6074 | + | |
6075 | + for (int i = 0; i < tags.length; i++) { | |
6076 | + decTags[i] = new String(this.dataDecoding(tags[i].getBytes())); | |
6077 | + } | |
6078 | + | |
6079 | + ret[1] = decTags; | |
6080 | + } | |
6081 | + } else if(serverRet[1].equals("false")) { | |
6082 | + | |
6083 | + // データなし | |
6084 | + ret[0] = serverRet[1]; | |
6085 | + ret[1] = null; | |
6086 | + } else if(serverRet[1].equals("error")) { | |
6087 | + | |
6088 | + // エラー発生 | |
6089 | + ret[0] = serverRet[1]; | |
6090 | + ret[1] = serverRet[2]; | |
6091 | + } | |
6092 | + } else { | |
6093 | + | |
6094 | + // 妥当性違反 | |
6095 | + throw new OkuyamaClientException("Execute Violation of validity [" + serverRet[0] + "]"); | |
6096 | + } | |
6097 | + } catch (OkuyamaClientException ice) { | |
6098 | + throw ice; | |
6099 | + } catch (ConnectException ce) { | |
6100 | + if (this.masterNodesList != null && masterNodesList.size() > 1) { | |
6101 | + try { | |
6102 | + this.autoConnect(); | |
6103 | + ret = this.getTargetIndexTagKeys(tagStr, bucketIndex); | |
6104 | + } catch (Exception e) { | |
6105 | + throw new OkuyamaClientException(ce); | |
6106 | + } | |
6107 | + } else { | |
6108 | + throw new OkuyamaClientException(ce); | |
6109 | + } | |
6110 | + } catch (SocketException se) { | |
6111 | + if (this.masterNodesList != null && masterNodesList.size() > 1) { | |
6112 | + try { | |
6113 | + this.autoConnect(); | |
6114 | + ret = this.getTargetIndexTagKeys(tagStr, bucketIndex); | |
6115 | + } catch (Exception e) { | |
6116 | + throw new OkuyamaClientException(se); | |
6117 | + } | |
6118 | + } else { | |
6119 | + throw new OkuyamaClientException(se); | |
6120 | + } | |
6121 | + } catch (Throwable e) { | |
6122 | + if (this.masterNodesList != null && masterNodesList.size() > 1) { | |
6123 | + try { | |
6124 | + this.autoConnect(); | |
6125 | + ret = this.getTargetIndexTagKeys(tagStr, bucketIndex); | |
6126 | + } catch (Exception ee) { | |
6127 | + throw new OkuyamaClientException(e); | |
6128 | + } | |
6129 | + } else { | |
6130 | + throw new OkuyamaClientException(e); | |
6131 | + } | |
6132 | + } | |
6133 | + return ret; | |
6134 | + } | |
6135 | + | |
6136 | + | |
6137 | + /** | |
5830 | 6138 | * MasterNodeからsetValueAndCreateIndexで作成されたIndexを使って検索して該当する値を取得する.<br> |
5831 | 6139 | * 検索可能な文字列は1文字からで、最大は128文字(ソフトリミット).<br> |
5832 | 6140 | * Prefxiなし.<br> |
@@ -0,0 +1,97 @@ | ||
1 | +package okuyama.imdst.client.result; | |
2 | + | |
3 | +import java.util.concurrent.LinkedBlockingQueue; | |
4 | + | |
5 | +import okuyama.imdst.client.*; | |
6 | + | |
7 | +/** | |
8 | + * OkuyamaClientのgetTagKeyResultで取得可能なクラス<br> | |
9 | + * 以下のような構文にてTagを利用して全ての紐付くKeyとValueを取得する<br> | |
10 | + * ----------------------------------------------------------------- | |
11 | + * OkuyamaResultSet resultSet = client.getTagKeyResult(tagStr); | |
12 | + * | |
13 | + * while(resultSet.next()) { | |
14 | + * System.out.println("Key=" + (Object)resultSet.getKey()); | |
15 | + * System.out.println("Value=" + (Object)resultSet.getValue()); | |
16 | + * } | |
17 | + * resultSet.close(); | |
18 | + * ------------------------------------------------------------------ | |
19 | + * | |
20 | + * | |
21 | + * @author T.Okuyama | |
22 | + * @license GPL(Lv3) | |
23 | + */ | |
24 | +public class OkuyamaTagKeysResultSet implements OkuyamaResultSet { | |
25 | + | |
26 | + protected OkuyamaClient client = null; | |
27 | + | |
28 | + protected String tagStr = null; | |
29 | + | |
30 | + protected String[] indexList = null; | |
31 | + | |
32 | + protected String encoding = null; | |
33 | + | |
34 | + private int nowIndex = 0; | |
35 | + | |
36 | + private boolean closeFlg = true; | |
37 | + | |
38 | + | |
39 | + private LinkedBlockingQueue keyQueue = null; | |
40 | + | |
41 | + private String nowKey = null; | |
42 | + | |
43 | + private String nowValue = null; | |
44 | + | |
45 | + | |
46 | + | |
47 | + /** | |
48 | + * コンストラクタ.<br> | |
49 | + * | |
50 | + * @param client | |
51 | + * @param tagStr | |
52 | + * @param indexList | |
53 | + */ | |
54 | + public OkuyamaTagKeysResultSet(OkuyamaClient client, String tagStr, String[] indexList, String encoding) { | |
55 | + this.client = client; | |
56 | + this.tagStr = tagStr; | |
57 | + this.indexList = indexList; | |
58 | + this.encoding = encoding; | |
59 | + this.keyQueue = new LinkedBlockingQueue(); | |
60 | + this.closeFlg = false; | |
61 | + } | |
62 | + | |
63 | + public boolean next() throws OkuyamaClientException { | |
64 | + | |
65 | + | |
66 | + return false; | |
67 | + } | |
68 | + | |
69 | + public Object getKey() throws OkuyamaClientException { | |
70 | + return null; | |
71 | + } | |
72 | + | |
73 | + public Object getValue() throws OkuyamaClientException { | |
74 | + return null; | |
75 | + } | |
76 | + | |
77 | + public void close() throws OkuyamaClientException { | |
78 | + try { | |
79 | + if (this.client != null) { | |
80 | + | |
81 | + this.client.close(); | |
82 | + this.client = null; | |
83 | + this.tagStr = null; | |
84 | + this.indexList = null; | |
85 | + this.nowIndex = -1; | |
86 | + } | |
87 | + this.closeFlg = true; | |
88 | + } catch (Exception e) { | |
89 | + throw new OkuyamaClientException(e); | |
90 | + } | |
91 | + | |
92 | + } | |
93 | + | |
94 | + public boolean isClose(){ | |
95 | + return this.closeFlg; | |
96 | + } | |
97 | +} | |
\ No newline at end of file |