1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <sys/time.h>
22 #include <poll.h>
23
24 #include <iostream>
25
26 #include <boost/lexical_cast.hpp>
27 #include <protocol/TBinaryProtocol.h>
28 #include <transport/TSocket.h>
29 #include <transport/TTransportUtils.h>
30
31 #include "Hbase.h"
32
33 using namespace apache::thrift;
34 using namespace apache::thrift::protocol;
35 using namespace apache::thrift::transport;
36
37 using namespace apache::hadoop::hbase::thrift;
38
39 namespace {
40
41 typedef std::vector<std::string> StrVec;
42 typedef std::map<std::string,std::string> StrMap;
43 typedef std::vector<ColumnDescriptor> ColVec;
44 typedef std::map<std::string,ColumnDescriptor> ColMap;
45 typedef std::vector<TCell> CellVec;
46 typedef std::map<std::string,TCell> CellMap;
47
48
49 static void
printRow(const std::vector<TRowResult> & rowResult)50 printRow(const std::vector<TRowResult> &rowResult)
51 {
52 for (size_t i = 0; i < rowResult.size(); i++) {
53 std::cout << "row: " << rowResult[i].row << ", cols: ";
54 for (CellMap::const_iterator it = rowResult[i].columns.begin();
55 it != rowResult[i].columns.end(); ++it) {
56 std::cout << it->first << " => " << it->second.value << "; ";
57 }
58 std::cout << std::endl;
59 }
60 }
61
62 static void
printVersions(const std::string & row,const CellVec & versions)63 printVersions(const std::string &row, const CellVec &versions)
64 {
65 std::cout << "row: " << row << ", values: ";
66 for (CellVec::const_iterator it = versions.begin(); it != versions.end(); ++it) {
67 std::cout << (*it).value << "; ";
68 }
69 std::cout << std::endl;
70 }
71
72 }
73
74 int
main(int argc,char ** argv)75 main(int argc, char** argv)
76 {
77 if (argc < 3) {
78 std::cerr << "Invalid arguments!\n" << "Usage: DemoClient host port" << std::endl;
79 return -1;
80 }
81 bool isFramed = false;
82 boost::shared_ptr<TTransport> socket(new TSocket(argv[1], boost::lexical_cast<int>(argv[2])));
83 boost::shared_ptr<TTransport> transport;
84
85 if (isFramed) {
86 transport.reset(new TFramedTransport(socket));
87 } else {
88 transport.reset(new TBufferedTransport(socket));
89 }
90 boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
91
92 const std::map<Text, Text> dummyAttributes; // see HBASE-6806 HBASE-4658
93 HbaseClient client(protocol);
94 try {
95 transport->open();
96
97 std::string t("demo_table");
98
99 //
100 // Scan all tables, look for the demo table and delete it.
101 //
102 std::cout << "scanning tables..." << std::endl;
103 StrVec tables;
104 client.getTableNames(tables);
105 for (StrVec::const_iterator it = tables.begin(); it != tables.end(); ++it) {
106 std::cout << " found: " << *it << std::endl;
107 if (t == *it) {
108 if (client.isTableEnabled(*it)) {
109 std::cout << " disabling table: " << *it << std::endl;
110 client.disableTable(*it);
111 }
112 std::cout << " deleting table: " << *it << std::endl;
113 client.deleteTable(*it);
114 }
115 }
116
117 //
118 // Create the demo table with two column families, entry: and unused:
119 //
120 ColVec columns;
121 columns.push_back(ColumnDescriptor());
122 columns.back().name = "entry:";
123 columns.back().maxVersions = 10;
124 columns.push_back(ColumnDescriptor());
125 columns.back().name = "unused:";
126
127 std::cout << "creating table: " << t << std::endl;
128 try {
129 client.createTable(t, columns);
130 } catch (const AlreadyExists &ae) {
131 std::cerr << "WARN: " << ae.message << std::endl;
132 }
133
134 ColMap columnMap;
135 client.getColumnDescriptors(columnMap, t);
136 std::cout << "column families in " << t << ": " << std::endl;
137 for (ColMap::const_iterator it = columnMap.begin(); it != columnMap.end(); ++it) {
138 std::cout << " column: " << it->second.name << ", maxVer: " << it->second.maxVersions << std::endl;
139 }
140
141 //
142 // Test UTF-8 handling
143 //
144 std::string invalid("foo-\xfc\xa1\xa1\xa1\xa1\xa1");
145 std::string valid("foo-\xE7\x94\x9F\xE3\x83\x93\xE3\x83\xBC\xE3\x83\xAB");
146
147 // non-utf8 is fine for data
148 std::vector<Mutation> mutations;
149 mutations.push_back(Mutation());
150 mutations.back().column = "entry:foo";
151 mutations.back().value = invalid;
152 client.mutateRow(t, "foo", mutations, dummyAttributes);
153
154 // try empty strings
155 mutations.clear();
156 mutations.push_back(Mutation());
157 mutations.back().column = "entry:";
158 mutations.back().value = "";
159 client.mutateRow(t, "", mutations, dummyAttributes);
160
161 // this row name is valid utf8
162 mutations.clear();
163 mutations.push_back(Mutation());
164 mutations.back().column = "entry:foo";
165 mutations.back().value = valid;
166 client.mutateRow(t, valid, mutations, dummyAttributes);
167
168 // non-utf8 is now allowed in row names because HBase stores values as binary
169 mutations.clear();
170 mutations.push_back(Mutation());
171 mutations.back().column = "entry:foo";
172 mutations.back().value = invalid;
173 client.mutateRow(t, invalid, mutations, dummyAttributes);
174
175 // Run a scanner on the rows we just created
176 StrVec columnNames;
177 columnNames.push_back("entry:");
178
179 std::cout << "Starting scanner..." << std::endl;
180 int scanner = client.scannerOpen(t, "", columnNames, dummyAttributes);
181 try {
182 while (true) {
183 std::vector<TRowResult> value;
184 client.scannerGet(value, scanner);
185 if (value.size() == 0)
186 break;
187 printRow(value);
188 }
189 } catch (const IOError &ioe) {
190 std::cerr << "FATAL: Scanner raised IOError" << std::endl;
191 }
192
193 client.scannerClose(scanner);
194 std::cout << "Scanner finished" << std::endl;
195
196 //
197 // Run some operations on a bunch of rows.
198 //
199 for (int i = 100; i >= 0; --i) {
200 // format row keys as "00000" to "00100"
201 char buf[32];
202 sprintf(buf, "%05d", i);
203 std::string row(buf);
204 std::vector<TRowResult> rowResult;
205
206 mutations.clear();
207 mutations.push_back(Mutation());
208 mutations.back().column = "unused:";
209 mutations.back().value = "DELETE_ME";
210 client.mutateRow(t, row, mutations, dummyAttributes);
211 client.getRow(rowResult, t, row, dummyAttributes);
212 printRow(rowResult);
213 client.deleteAllRow(t, row, dummyAttributes);
214
215 mutations.clear();
216 mutations.push_back(Mutation());
217 mutations.back().column = "entry:num";
218 mutations.back().value = "0";
219 mutations.push_back(Mutation());
220 mutations.back().column = "entry:foo";
221 mutations.back().value = "FOO";
222 client.mutateRow(t, row, mutations, dummyAttributes);
223 client.getRow(rowResult, t, row, dummyAttributes);
224 printRow(rowResult);
225
226 // sleep to force later timestamp
227 poll(0, 0, 50);
228
229 mutations.clear();
230 mutations.push_back(Mutation());
231 mutations.back().column = "entry:foo";
232 mutations.back().isDelete = true;
233 mutations.push_back(Mutation());
234 mutations.back().column = "entry:num";
235 mutations.back().value = "-1";
236 client.mutateRow(t, row, mutations, dummyAttributes);
237 client.getRow(rowResult, t, row, dummyAttributes);
238 printRow(rowResult);
239
240 mutations.clear();
241 mutations.push_back(Mutation());
242 mutations.back().column = "entry:num";
243 mutations.back().value = boost::lexical_cast<std::string>(i);
244 mutations.push_back(Mutation());
245 mutations.back().column = "entry:sqr";
246 mutations.back().value = boost::lexical_cast<std::string>(i*i);
247 client.mutateRow(t, row, mutations, dummyAttributes);
248 client.getRow(rowResult, t, row, dummyAttributes);
249 printRow(rowResult);
250
251 mutations.clear();
252 mutations.push_back(Mutation());
253 mutations.back().column = "entry:num";
254 mutations.back().value = "-999";
255 mutations.push_back(Mutation());
256 mutations.back().column = "entry:sqr";
257 mutations.back().isDelete = true;
258 client.mutateRowTs(t, row, mutations, 1, dummyAttributes); // shouldn't override latest
259 client.getRow(rowResult, t, row, dummyAttributes);
260 printRow(rowResult);
261
262 CellVec versions;
263 client.getVer(versions, t, row, "entry:num", 10, dummyAttributes);
264 printVersions(row, versions);
265 assert(versions.size());
266 std::cout << std::endl;
267
268 try {
269 std::vector<TCell> value;
270 client.get(value, t, row, "entry:foo", dummyAttributes);
271 if (value.size()) {
272 std::cerr << "FATAL: shouldn't get here!" << std::endl;
273 return -1;
274 }
275 } catch (const IOError &ioe) {
276 // blank
277 }
278 }
279
280 // scan all rows/columns
281
282 columnNames.clear();
283 client.getColumnDescriptors(columnMap, t);
284 std::cout << "The number of columns: " << columnMap.size() << std::endl;
285 for (ColMap::const_iterator it = columnMap.begin(); it != columnMap.end(); ++it) {
286 std::cout << " column with name: " + it->second.name << std::endl;
287 columnNames.push_back(it->second.name);
288 }
289 std::cout << std::endl;
290
291 std::cout << "Starting scanner..." << std::endl;
292 scanner = client.scannerOpenWithStop(t, "00020", "00040", columnNames, dummyAttributes);
293 try {
294 while (true) {
295 std::vector<TRowResult> value;
296 client.scannerGet(value, scanner);
297 if (value.size() == 0)
298 break;
299 printRow(value);
300 }
301 } catch (const IOError &ioe) {
302 std::cerr << "FATAL: Scanner raised IOError" << std::endl;
303 }
304
305 client.scannerClose(scanner);
306 std::cout << "Scanner finished" << std::endl;
307
308 transport->close();
309 } catch (const TException &tx) {
310 std::cerr << "ERROR: " << tx.what() << std::endl;
311 }
312 }
313