1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.thrift;
20
21 import static org.apache.hadoop.hbase.util.Bytes.getBytes;
22
23 import java.io.IOException;
24 import java.net.InetAddress;
25 import java.net.InetSocketAddress;
26 import java.net.UnknownHostException;
27 import java.nio.ByteBuffer;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.TreeMap;
35 import java.util.concurrent.BlockingQueue;
36 import java.util.concurrent.ExecutorService;
37 import java.util.concurrent.LinkedBlockingQueue;
38 import java.util.concurrent.ThreadPoolExecutor;
39 import java.util.concurrent.TimeUnit;
40
41 import org.apache.commons.cli.CommandLine;
42 import org.apache.commons.cli.Option;
43 import org.apache.commons.cli.OptionGroup;
44 import org.apache.commons.logging.Log;
45 import org.apache.commons.logging.LogFactory;
46 import org.apache.hadoop.classification.InterfaceAudience;
47 import org.apache.hadoop.conf.Configuration;
48 import org.apache.hadoop.hbase.HBaseConfiguration;
49 import org.apache.hadoop.hbase.HColumnDescriptor;
50 import org.apache.hadoop.hbase.HConstants;
51 import org.apache.hadoop.hbase.HRegionInfo;
52 import org.apache.hadoop.hbase.HTableDescriptor;
53 import org.apache.hadoop.hbase.KeyValue;
54 import org.apache.hadoop.hbase.ServerName;
55 import org.apache.hadoop.hbase.exceptions.TableNotFoundException;
56 import org.apache.hadoop.hbase.client.Delete;
57 import org.apache.hadoop.hbase.client.Get;
58 import org.apache.hadoop.hbase.client.HBaseAdmin;
59 import org.apache.hadoop.hbase.client.HTable;
60 import org.apache.hadoop.hbase.client.Increment;
61 import org.apache.hadoop.hbase.client.OperationWithAttributes;
62 import org.apache.hadoop.hbase.client.Put;
63 import org.apache.hadoop.hbase.client.Result;
64 import org.apache.hadoop.hbase.client.ResultScanner;
65 import org.apache.hadoop.hbase.client.Scan;
66 import org.apache.hadoop.hbase.filter.Filter;
67 import org.apache.hadoop.hbase.filter.ParseFilter;
68 import org.apache.hadoop.hbase.filter.PrefixFilter;
69 import org.apache.hadoop.hbase.filter.WhileMatchFilter;
70 import org.apache.hadoop.hbase.thrift.CallQueue.Call;
71 import org.apache.hadoop.hbase.thrift.generated.AlreadyExists;
72 import org.apache.hadoop.hbase.thrift.generated.BatchMutation;
73 import org.apache.hadoop.hbase.thrift.generated.ColumnDescriptor;
74 import org.apache.hadoop.hbase.thrift.generated.Hbase;
75 import org.apache.hadoop.hbase.thrift.generated.IOError;
76 import org.apache.hadoop.hbase.thrift.generated.IllegalArgument;
77 import org.apache.hadoop.hbase.thrift.generated.Mutation;
78 import org.apache.hadoop.hbase.thrift.generated.TCell;
79 import org.apache.hadoop.hbase.thrift.generated.TIncrement;
80 import org.apache.hadoop.hbase.thrift.generated.TRegionInfo;
81 import org.apache.hadoop.hbase.thrift.generated.TRowResult;
82 import org.apache.hadoop.hbase.thrift.generated.TScan;
83 import org.apache.hadoop.hbase.util.Bytes;
84 import org.apache.thrift.TException;
85 import org.apache.thrift.protocol.TBinaryProtocol;
86 import org.apache.thrift.protocol.TCompactProtocol;
87 import org.apache.thrift.protocol.TProtocolFactory;
88 import org.apache.thrift.server.THsHaServer;
89 import org.apache.thrift.server.TNonblockingServer;
90 import org.apache.thrift.server.TServer;
91 import org.apache.thrift.server.TThreadedSelectorServer;
92 import org.apache.thrift.transport.TFramedTransport;
93 import org.apache.thrift.transport.TNonblockingServerSocket;
94 import org.apache.thrift.transport.TNonblockingServerTransport;
95 import org.apache.thrift.transport.TServerSocket;
96 import org.apache.thrift.transport.TServerTransport;
97 import org.apache.thrift.transport.TTransportFactory;
98
99 import com.google.common.base.Joiner;
100 import com.google.common.util.concurrent.ThreadFactoryBuilder;
101
102
103
104
105
106 @InterfaceAudience.Private
107 public class ThriftServerRunner implements Runnable {
108
109 private static final Log LOG = LogFactory.getLog(ThriftServerRunner.class);
110
111 static final String SERVER_TYPE_CONF_KEY =
112 "hbase.regionserver.thrift.server.type";
113
114 static final String BIND_CONF_KEY = "hbase.regionserver.thrift.ipaddress";
115 static final String COMPACT_CONF_KEY = "hbase.regionserver.thrift.compact";
116 static final String FRAMED_CONF_KEY = "hbase.regionserver.thrift.framed";
117 static final String PORT_CONF_KEY = "hbase.regionserver.thrift.port";
118 static final String COALESCE_INC_KEY = "hbase.regionserver.thrift.coalesceIncrement";
119
120 private static final String DEFAULT_BIND_ADDR = "0.0.0.0";
121 public static final int DEFAULT_LISTEN_PORT = 9090;
122 private final int listenPort;
123
124 private Configuration conf;
125 volatile TServer tserver;
126 private final Hbase.Iface handler;
127 private final ThriftMetrics metrics;
128
129
130 enum ImplType {
131 HS_HA("hsha", true, THsHaServer.class, true),
132 NONBLOCKING("nonblocking", true, TNonblockingServer.class, true),
133 THREAD_POOL("threadpool", false, TBoundedThreadPoolServer.class, true),
134 THREADED_SELECTOR(
135 "threadedselector", true, TThreadedSelectorServer.class, true);
136
137 public static final ImplType DEFAULT = THREAD_POOL;
138
139 final String option;
140 final boolean isAlwaysFramed;
141 final Class<? extends TServer> serverClass;
142 final boolean canSpecifyBindIP;
143
144 ImplType(String option, boolean isAlwaysFramed,
145 Class<? extends TServer> serverClass, boolean canSpecifyBindIP) {
146 this.option = option;
147 this.isAlwaysFramed = isAlwaysFramed;
148 this.serverClass = serverClass;
149 this.canSpecifyBindIP = canSpecifyBindIP;
150 }
151
152
153
154
155
156 @Override
157 public String toString() {
158 return "-" + option;
159 }
160
161 String getDescription() {
162 StringBuilder sb = new StringBuilder("Use the " +
163 serverClass.getSimpleName());
164 if (isAlwaysFramed) {
165 sb.append(" This implies the framed transport.");
166 }
167 if (this == DEFAULT) {
168 sb.append("This is the default.");
169 }
170 return sb.toString();
171 }
172
173 static OptionGroup createOptionGroup() {
174 OptionGroup group = new OptionGroup();
175 for (ImplType t : values()) {
176 group.addOption(new Option(t.option, t.getDescription()));
177 }
178 return group;
179 }
180
181 static ImplType getServerImpl(Configuration conf) {
182 String confType = conf.get(SERVER_TYPE_CONF_KEY, THREAD_POOL.option);
183 for (ImplType t : values()) {
184 if (confType.equals(t.option)) {
185 return t;
186 }
187 }
188 throw new AssertionError("Unknown server ImplType.option:" + confType);
189 }
190
191 static void setServerImpl(CommandLine cmd, Configuration conf) {
192 ImplType chosenType = null;
193 int numChosen = 0;
194 for (ImplType t : values()) {
195 if (cmd.hasOption(t.option)) {
196 chosenType = t;
197 ++numChosen;
198 }
199 }
200 if (numChosen < 1) {
201 LOG.info("Using default thrift server type");
202 chosenType = DEFAULT;
203 } else if (numChosen > 1) {
204 throw new AssertionError("Exactly one option out of " +
205 Arrays.toString(values()) + " has to be specified");
206 }
207 LOG.info("Using thrift server type " + chosenType.option);
208 conf.set(SERVER_TYPE_CONF_KEY, chosenType.option);
209 }
210
211 public String simpleClassName() {
212 return serverClass.getSimpleName();
213 }
214
215 public static List<String> serversThatCannotSpecifyBindIP() {
216 List<String> l = new ArrayList<String>();
217 for (ImplType t : values()) {
218 if (!t.canSpecifyBindIP) {
219 l.add(t.simpleClassName());
220 }
221 }
222 return l;
223 }
224
225 }
226
227 public ThriftServerRunner(Configuration conf) throws IOException {
228 this(conf, new ThriftServerRunner.HBaseHandler(conf));
229 }
230
231 public ThriftServerRunner(Configuration conf, HBaseHandler handler) {
232 this.conf = HBaseConfiguration.create(conf);
233 this.listenPort = conf.getInt(PORT_CONF_KEY, DEFAULT_LISTEN_PORT);
234 this.metrics = new ThriftMetrics(conf, ThriftMetrics.ThriftServerType.ONE);
235 handler.initMetrics(metrics);
236 this.handler = HbaseHandlerMetricsProxy.newInstance(handler, metrics, conf);
237 }
238
239
240
241
242 @Override
243 public void run() {
244 try {
245 setupServer();
246 tserver.serve();
247 } catch (Exception e) {
248 LOG.fatal("Cannot run ThriftServer", e);
249
250 System.exit(-1);
251 }
252 }
253
254 public void shutdown() {
255 if (tserver != null) {
256 tserver.stop();
257 tserver = null;
258 }
259 }
260
261
262
263
264 private void setupServer() throws Exception {
265
266 TProtocolFactory protocolFactory;
267 if (conf.getBoolean(COMPACT_CONF_KEY, false)) {
268 LOG.debug("Using compact protocol");
269 protocolFactory = new TCompactProtocol.Factory();
270 } else {
271 LOG.debug("Using binary protocol");
272 protocolFactory = new TBinaryProtocol.Factory();
273 }
274
275 Hbase.Processor<Hbase.Iface> processor =
276 new Hbase.Processor<Hbase.Iface>(handler);
277 ImplType implType = ImplType.getServerImpl(conf);
278
279
280 TTransportFactory transportFactory;
281 if (conf.getBoolean(FRAMED_CONF_KEY, false) || implType.isAlwaysFramed) {
282 transportFactory = new TFramedTransport.Factory();
283 LOG.debug("Using framed transport");
284 } else {
285 transportFactory = new TTransportFactory();
286 }
287
288 if (conf.get(BIND_CONF_KEY) != null && !implType.canSpecifyBindIP) {
289 LOG.error("Server types " + Joiner.on(", ").join(
290 ImplType.serversThatCannotSpecifyBindIP()) + " don't support IP " +
291 "address binding at the moment. See " +
292 "https://issues.apache.org/jira/browse/HBASE-2155 for details.");
293 throw new RuntimeException(
294 "-" + BIND_CONF_KEY + " not supported with " + implType);
295 }
296
297 if (implType == ImplType.HS_HA || implType == ImplType.NONBLOCKING ||
298 implType == ImplType.THREADED_SELECTOR) {
299
300 InetAddress listenAddress = getBindAddress(conf);
301 TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(
302 new InetSocketAddress(listenAddress, listenPort));
303
304 if (implType == ImplType.NONBLOCKING) {
305 TNonblockingServer.Args serverArgs =
306 new TNonblockingServer.Args(serverTransport);
307 serverArgs.processor(processor)
308 .transportFactory(transportFactory)
309 .protocolFactory(protocolFactory);
310 tserver = new TNonblockingServer(serverArgs);
311 } else if (implType == ImplType.HS_HA) {
312 THsHaServer.Args serverArgs = new THsHaServer.Args(serverTransport);
313 CallQueue callQueue =
314 new CallQueue(new LinkedBlockingQueue<Call>(), metrics);
315 ExecutorService executorService = createExecutor(
316 callQueue, serverArgs.getWorkerThreads());
317 serverArgs.executorService(executorService)
318 .processor(processor)
319 .transportFactory(transportFactory)
320 .protocolFactory(protocolFactory);
321 tserver = new THsHaServer(serverArgs);
322 } else {
323 TThreadedSelectorServer.Args serverArgs =
324 new HThreadedSelectorServerArgs(serverTransport, conf);
325 CallQueue callQueue =
326 new CallQueue(new LinkedBlockingQueue<Call>(), metrics);
327 ExecutorService executorService = createExecutor(
328 callQueue, serverArgs.getWorkerThreads());
329 serverArgs.executorService(executorService)
330 .processor(processor)
331 .transportFactory(transportFactory)
332 .protocolFactory(protocolFactory);
333 tserver = new TThreadedSelectorServer(serverArgs);
334 }
335 LOG.info("starting HBase " + implType.simpleClassName() +
336 " server on " + Integer.toString(listenPort));
337 } else if (implType == ImplType.THREAD_POOL) {
338
339 InetAddress listenAddress = getBindAddress(conf);
340
341 TServerTransport serverTransport = new TServerSocket(
342 new InetSocketAddress(listenAddress, listenPort));
343
344 TBoundedThreadPoolServer.Args serverArgs =
345 new TBoundedThreadPoolServer.Args(serverTransport, conf);
346 serverArgs.processor(processor)
347 .transportFactory(transportFactory)
348 .protocolFactory(protocolFactory);
349 LOG.info("starting " + ImplType.THREAD_POOL.simpleClassName() + " on "
350 + listenAddress + ":" + Integer.toString(listenPort)
351 + "; " + serverArgs);
352 TBoundedThreadPoolServer tserver =
353 new TBoundedThreadPoolServer(serverArgs, metrics);
354 this.tserver = tserver;
355 } else {
356 throw new AssertionError("Unsupported Thrift server implementation: " +
357 implType.simpleClassName());
358 }
359
360
361 if (tserver.getClass() != implType.serverClass) {
362 throw new AssertionError("Expected to create Thrift server class " +
363 implType.serverClass.getName() + " but got " +
364 tserver.getClass().getName());
365 }
366
367
368
369 registerFilters(conf);
370 }
371
372 ExecutorService createExecutor(BlockingQueue<Runnable> callQueue,
373 int workerThreads) {
374 ThreadFactoryBuilder tfb = new ThreadFactoryBuilder();
375 tfb.setDaemon(true);
376 tfb.setNameFormat("thrift-worker-%d");
377 return new ThreadPoolExecutor(workerThreads, workerThreads,
378 Long.MAX_VALUE, TimeUnit.SECONDS, callQueue, tfb.build());
379 }
380
381 private InetAddress getBindAddress(Configuration conf)
382 throws UnknownHostException {
383 String bindAddressStr = conf.get(BIND_CONF_KEY, DEFAULT_BIND_ADDR);
384 return InetAddress.getByName(bindAddressStr);
385 }
386
387
388
389
390
391 public static class HBaseHandler implements Hbase.Iface {
392 protected Configuration conf;
393 protected volatile HBaseAdmin admin = null;
394 protected final Log LOG = LogFactory.getLog(this.getClass().getName());
395
396
397 protected int nextScannerId = 0;
398 protected HashMap<Integer, ResultScanner> scannerMap = null;
399 private ThriftMetrics metrics = null;
400
401 private static ThreadLocal<Map<String, HTable>> threadLocalTables =
402 new ThreadLocal<Map<String, HTable>>() {
403 @Override
404 protected Map<String, HTable> initialValue() {
405 return new TreeMap<String, HTable>();
406 }
407 };
408
409 IncrementCoalescer coalescer = null;
410
411
412
413
414
415
416
417
418 byte[][] getAllColumns(HTable table) throws IOException {
419 HColumnDescriptor[] cds = table.getTableDescriptor().getColumnFamilies();
420 byte[][] columns = new byte[cds.length][];
421 for (int i = 0; i < cds.length; i++) {
422 columns[i] = Bytes.add(cds[i].getName(),
423 KeyValue.COLUMN_FAMILY_DELIM_ARRAY);
424 }
425 return columns;
426 }
427
428
429
430
431
432
433
434
435
436
437 public HTable getTable(final byte[] tableName) throws
438 IOException {
439 String table = new String(tableName);
440 Map<String, HTable> tables = threadLocalTables.get();
441 if (!tables.containsKey(table)) {
442 tables.put(table, new HTable(conf, tableName));
443 }
444 return tables.get(table);
445 }
446
447 public HTable getTable(final ByteBuffer tableName) throws IOException {
448 return getTable(getBytes(tableName));
449 }
450
451
452
453
454
455
456
457
458 protected synchronized int addScanner(ResultScanner scanner) {
459 int id = nextScannerId++;
460 scannerMap.put(id, scanner);
461 return id;
462 }
463
464
465
466
467
468
469
470 protected synchronized ResultScanner getScanner(int id) {
471 return scannerMap.get(id);
472 }
473
474
475
476
477
478
479
480
481 protected synchronized ResultScanner removeScanner(int id) {
482 return scannerMap.remove(id);
483 }
484
485
486
487
488
489 protected HBaseHandler()
490 throws IOException {
491 this(HBaseConfiguration.create());
492 }
493
494 protected HBaseHandler(final Configuration c) throws IOException {
495 this.conf = c;
496 scannerMap = new HashMap<Integer, ResultScanner>();
497 this.coalescer = new IncrementCoalescer(this);
498 }
499
500
501
502
503 private HBaseAdmin getHBaseAdmin() throws IOException {
504 if (admin == null) {
505 synchronized (this) {
506 if (admin == null) {
507 admin = new HBaseAdmin(conf);
508 }
509 }
510 }
511 return admin;
512 }
513
514 @Override
515 public void enableTable(ByteBuffer tableName) throws IOError {
516 try{
517 getHBaseAdmin().enableTable(getBytes(tableName));
518 } catch (IOException e) {
519 LOG.warn(e.getMessage(), e);
520 throw new IOError(e.getMessage());
521 }
522 }
523
524 @Override
525 public void disableTable(ByteBuffer tableName) throws IOError{
526 try{
527 getHBaseAdmin().disableTable(getBytes(tableName));
528 } catch (IOException e) {
529 LOG.warn(e.getMessage(), e);
530 throw new IOError(e.getMessage());
531 }
532 }
533
534 @Override
535 public boolean isTableEnabled(ByteBuffer tableName) throws IOError {
536 try {
537 return HTable.isTableEnabled(this.conf, getBytes(tableName));
538 } catch (IOException e) {
539 LOG.warn(e.getMessage(), e);
540 throw new IOError(e.getMessage());
541 }
542 }
543
544 @Override
545 public void compact(ByteBuffer tableNameOrRegionName) throws IOError {
546 try{
547 getHBaseAdmin().compact(getBytes(tableNameOrRegionName));
548 } catch (InterruptedException e) {
549 throw new IOError(e.getMessage());
550 } catch (IOException e) {
551 LOG.warn(e.getMessage(), e);
552 throw new IOError(e.getMessage());
553 }
554 }
555
556 @Override
557 public void majorCompact(ByteBuffer tableNameOrRegionName) throws IOError {
558 try{
559 getHBaseAdmin().majorCompact(getBytes(tableNameOrRegionName));
560 } catch (InterruptedException e) {
561 LOG.warn(e.getMessage(), e);
562 throw new IOError(e.getMessage());
563 } catch (IOException e) {
564 LOG.warn(e.getMessage(), e);
565 throw new IOError(e.getMessage());
566 }
567 }
568
569 @Override
570 public List<ByteBuffer> getTableNames() throws IOError {
571 try {
572 HTableDescriptor[] tables = this.getHBaseAdmin().listTables();
573 ArrayList<ByteBuffer> list = new ArrayList<ByteBuffer>(tables.length);
574 for (int i = 0; i < tables.length; i++) {
575 list.add(ByteBuffer.wrap(tables[i].getName()));
576 }
577 return list;
578 } catch (IOException e) {
579 LOG.warn(e.getMessage(), e);
580 throw new IOError(e.getMessage());
581 }
582 }
583
584
585
586
587 @Override
588 public List<TRegionInfo> getTableRegions(ByteBuffer tableName)
589 throws IOError {
590 try {
591 HTable table;
592 try {
593 table = getTable(tableName);
594 } catch (TableNotFoundException ex) {
595 return new ArrayList<TRegionInfo>();
596 }
597 Map<HRegionInfo, ServerName> regionLocations =
598 table.getRegionLocations();
599 List<TRegionInfo> results = new ArrayList<TRegionInfo>();
600 for (Map.Entry<HRegionInfo, ServerName> entry :
601 regionLocations.entrySet()) {
602 HRegionInfo info = entry.getKey();
603 ServerName serverName = entry.getValue();
604 TRegionInfo region = new TRegionInfo();
605 region.serverName = ByteBuffer.wrap(
606 Bytes.toBytes(serverName.getHostname()));
607 region.port = serverName.getPort();
608 region.startKey = ByteBuffer.wrap(info.getStartKey());
609 region.endKey = ByteBuffer.wrap(info.getEndKey());
610 region.id = info.getRegionId();
611 region.name = ByteBuffer.wrap(info.getRegionName());
612 region.version = info.getVersion();
613 results.add(region);
614 }
615 return results;
616 } catch (TableNotFoundException e) {
617
618 return Collections.emptyList();
619 } catch (IOException e){
620 LOG.warn(e.getMessage(), e);
621 throw new IOError(e.getMessage());
622 }
623 }
624
625 @Deprecated
626 @Override
627 public List<TCell> get(
628 ByteBuffer tableName, ByteBuffer row, ByteBuffer column,
629 Map<ByteBuffer, ByteBuffer> attributes)
630 throws IOError {
631 byte [][] famAndQf = KeyValue.parseColumn(getBytes(column));
632 if(famAndQf.length == 1) {
633 return get(tableName, row, famAndQf[0], new byte[0], attributes);
634 }
635 return get(tableName, row, famAndQf[0], famAndQf[1], attributes);
636 }
637
638 protected List<TCell> get(ByteBuffer tableName,
639 ByteBuffer row,
640 byte[] family,
641 byte[] qualifier,
642 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
643 try {
644 HTable table = getTable(tableName);
645 Get get = new Get(getBytes(row));
646 addAttributes(get, attributes);
647 if (qualifier == null || qualifier.length == 0) {
648 get.addFamily(family);
649 } else {
650 get.addColumn(family, qualifier);
651 }
652 Result result = table.get(get);
653 return ThriftUtilities.cellFromHBase(result.raw());
654 } catch (IOException e) {
655 LOG.warn(e.getMessage(), e);
656 throw new IOError(e.getMessage());
657 }
658 }
659
660 @Deprecated
661 @Override
662 public List<TCell> getVer(ByteBuffer tableName, ByteBuffer row,
663 ByteBuffer column, int numVersions,
664 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
665 byte [][] famAndQf = KeyValue.parseColumn(getBytes(column));
666 if(famAndQf.length == 1) {
667 return getVer(tableName, row, famAndQf[0],
668 new byte[0], numVersions, attributes);
669 }
670 return getVer(tableName, row,
671 famAndQf[0], famAndQf[1], numVersions, attributes);
672 }
673
674 public List<TCell> getVer(ByteBuffer tableName, ByteBuffer row,
675 byte[] family,
676 byte[] qualifier, int numVersions,
677 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
678 try {
679 HTable table = getTable(tableName);
680 Get get = new Get(getBytes(row));
681 addAttributes(get, attributes);
682 get.addColumn(family, qualifier);
683 get.setMaxVersions(numVersions);
684 Result result = table.get(get);
685 return ThriftUtilities.cellFromHBase(result.raw());
686 } catch (IOException e) {
687 LOG.warn(e.getMessage(), e);
688 throw new IOError(e.getMessage());
689 }
690 }
691
692 @Deprecated
693 @Override
694 public List<TCell> getVerTs(ByteBuffer tableName,
695 ByteBuffer row,
696 ByteBuffer column,
697 long timestamp,
698 int numVersions,
699 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
700 byte [][] famAndQf = KeyValue.parseColumn(getBytes(column));
701 if(famAndQf.length == 1) {
702 return getVerTs(tableName, row, famAndQf[0], new byte[0], timestamp,
703 numVersions, attributes);
704 }
705 return getVerTs(tableName, row, famAndQf[0], famAndQf[1], timestamp,
706 numVersions, attributes);
707 }
708
709 protected List<TCell> getVerTs(ByteBuffer tableName,
710 ByteBuffer row, byte [] family,
711 byte [] qualifier, long timestamp, int numVersions,
712 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
713 try {
714 HTable table = getTable(tableName);
715 Get get = new Get(getBytes(row));
716 addAttributes(get, attributes);
717 get.addColumn(family, qualifier);
718 get.setTimeRange(Long.MIN_VALUE, timestamp);
719 get.setMaxVersions(numVersions);
720 Result result = table.get(get);
721 return ThriftUtilities.cellFromHBase(result.raw());
722 } catch (IOException e) {
723 LOG.warn(e.getMessage(), e);
724 throw new IOError(e.getMessage());
725 }
726 }
727
728 @Override
729 public List<TRowResult> getRow(ByteBuffer tableName, ByteBuffer row,
730 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
731 return getRowWithColumnsTs(tableName, row, null,
732 HConstants.LATEST_TIMESTAMP,
733 attributes);
734 }
735
736 @Override
737 public List<TRowResult> getRowWithColumns(ByteBuffer tableName,
738 ByteBuffer row,
739 List<ByteBuffer> columns,
740 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
741 return getRowWithColumnsTs(tableName, row, columns,
742 HConstants.LATEST_TIMESTAMP,
743 attributes);
744 }
745
746 @Override
747 public List<TRowResult> getRowTs(ByteBuffer tableName, ByteBuffer row,
748 long timestamp, Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
749 return getRowWithColumnsTs(tableName, row, null,
750 timestamp, attributes);
751 }
752
753 @Override
754 public List<TRowResult> getRowWithColumnsTs(
755 ByteBuffer tableName, ByteBuffer row, List<ByteBuffer> columns,
756 long timestamp, Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
757 try {
758 HTable table = getTable(tableName);
759 if (columns == null) {
760 Get get = new Get(getBytes(row));
761 addAttributes(get, attributes);
762 get.setTimeRange(Long.MIN_VALUE, timestamp);
763 Result result = table.get(get);
764 return ThriftUtilities.rowResultFromHBase(result);
765 }
766 Get get = new Get(getBytes(row));
767 addAttributes(get, attributes);
768 for(ByteBuffer column : columns) {
769 byte [][] famAndQf = KeyValue.parseColumn(getBytes(column));
770 if (famAndQf.length == 1) {
771 get.addFamily(famAndQf[0]);
772 } else {
773 get.addColumn(famAndQf[0], famAndQf[1]);
774 }
775 }
776 get.setTimeRange(Long.MIN_VALUE, timestamp);
777 Result result = table.get(get);
778 return ThriftUtilities.rowResultFromHBase(result);
779 } catch (IOException e) {
780 LOG.warn(e.getMessage(), e);
781 throw new IOError(e.getMessage());
782 }
783 }
784
785 @Override
786 public List<TRowResult> getRows(ByteBuffer tableName,
787 List<ByteBuffer> rows,
788 Map<ByteBuffer, ByteBuffer> attributes)
789 throws IOError {
790 return getRowsWithColumnsTs(tableName, rows, null,
791 HConstants.LATEST_TIMESTAMP,
792 attributes);
793 }
794
795 @Override
796 public List<TRowResult> getRowsWithColumns(ByteBuffer tableName,
797 List<ByteBuffer> rows,
798 List<ByteBuffer> columns,
799 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
800 return getRowsWithColumnsTs(tableName, rows, columns,
801 HConstants.LATEST_TIMESTAMP,
802 attributes);
803 }
804
805 @Override
806 public List<TRowResult> getRowsTs(ByteBuffer tableName,
807 List<ByteBuffer> rows,
808 long timestamp,
809 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
810 return getRowsWithColumnsTs(tableName, rows, null,
811 timestamp, attributes);
812 }
813
814 @Override
815 public List<TRowResult> getRowsWithColumnsTs(ByteBuffer tableName,
816 List<ByteBuffer> rows,
817 List<ByteBuffer> columns, long timestamp,
818 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
819 try {
820 List<Get> gets = new ArrayList<Get>(rows.size());
821 HTable table = getTable(tableName);
822 if (metrics != null) {
823 metrics.incNumRowKeysInBatchGet(rows.size());
824 }
825 for (ByteBuffer row : rows) {
826 Get get = new Get(getBytes(row));
827 addAttributes(get, attributes);
828 if (columns != null) {
829
830 for(ByteBuffer column : columns) {
831 byte [][] famAndQf = KeyValue.parseColumn(getBytes(column));
832 if (famAndQf.length == 1) {
833 get.addFamily(famAndQf[0]);
834 } else {
835 get.addColumn(famAndQf[0], famAndQf[1]);
836 }
837 }
838 }
839 get.setTimeRange(Long.MIN_VALUE, timestamp);
840 gets.add(get);
841 }
842 Result[] result = table.get(gets);
843 return ThriftUtilities.rowResultFromHBase(result);
844 } catch (IOException e) {
845 LOG.warn(e.getMessage(), e);
846 throw new IOError(e.getMessage());
847 }
848 }
849
850 @Override
851 public void deleteAll(
852 ByteBuffer tableName, ByteBuffer row, ByteBuffer column,
853 Map<ByteBuffer, ByteBuffer> attributes)
854 throws IOError {
855 deleteAllTs(tableName, row, column, HConstants.LATEST_TIMESTAMP,
856 attributes);
857 }
858
859 @Override
860 public void deleteAllTs(ByteBuffer tableName,
861 ByteBuffer row,
862 ByteBuffer column,
863 long timestamp, Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
864 try {
865 HTable table = getTable(tableName);
866 Delete delete = new Delete(getBytes(row));
867 addAttributes(delete, attributes);
868 byte [][] famAndQf = KeyValue.parseColumn(getBytes(column));
869 if (famAndQf.length == 1) {
870 delete.deleteFamily(famAndQf[0], timestamp);
871 } else {
872 delete.deleteColumns(famAndQf[0], famAndQf[1], timestamp);
873 }
874 table.delete(delete);
875
876 } catch (IOException e) {
877 LOG.warn(e.getMessage(), e);
878 throw new IOError(e.getMessage());
879 }
880 }
881
882 @Override
883 public void deleteAllRow(
884 ByteBuffer tableName, ByteBuffer row,
885 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
886 deleteAllRowTs(tableName, row, HConstants.LATEST_TIMESTAMP, attributes);
887 }
888
889 @Override
890 public void deleteAllRowTs(
891 ByteBuffer tableName, ByteBuffer row, long timestamp,
892 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
893 try {
894 HTable table = getTable(tableName);
895 Delete delete = new Delete(getBytes(row), timestamp);
896 addAttributes(delete, attributes);
897 table.delete(delete);
898 } catch (IOException e) {
899 LOG.warn(e.getMessage(), e);
900 throw new IOError(e.getMessage());
901 }
902 }
903
904 @Override
905 public void createTable(ByteBuffer in_tableName,
906 List<ColumnDescriptor> columnFamilies) throws IOError,
907 IllegalArgument, AlreadyExists {
908 byte [] tableName = getBytes(in_tableName);
909 try {
910 if (getHBaseAdmin().tableExists(tableName)) {
911 throw new AlreadyExists("table name already in use");
912 }
913 HTableDescriptor desc = new HTableDescriptor(tableName);
914 for (ColumnDescriptor col : columnFamilies) {
915 HColumnDescriptor colDesc = ThriftUtilities.colDescFromThrift(col);
916 desc.addFamily(colDesc);
917 }
918 getHBaseAdmin().createTable(desc);
919 } catch (IOException e) {
920 LOG.warn(e.getMessage(), e);
921 throw new IOError(e.getMessage());
922 } catch (IllegalArgumentException e) {
923 LOG.warn(e.getMessage(), e);
924 throw new IllegalArgument(e.getMessage());
925 }
926 }
927
928 @Override
929 public void deleteTable(ByteBuffer in_tableName) throws IOError {
930 byte [] tableName = getBytes(in_tableName);
931 if (LOG.isDebugEnabled()) {
932 LOG.debug("deleteTable: table=" + Bytes.toString(tableName));
933 }
934 try {
935 if (!getHBaseAdmin().tableExists(tableName)) {
936 throw new IOException("table does not exist");
937 }
938 getHBaseAdmin().deleteTable(tableName);
939 } catch (IOException e) {
940 LOG.warn(e.getMessage(), e);
941 throw new IOError(e.getMessage());
942 }
943 }
944
945 @Override
946 public void mutateRow(ByteBuffer tableName, ByteBuffer row,
947 List<Mutation> mutations, Map<ByteBuffer, ByteBuffer> attributes)
948 throws IOError, IllegalArgument {
949 mutateRowTs(tableName, row, mutations, HConstants.LATEST_TIMESTAMP,
950 attributes);
951 }
952
953 @Override
954 public void mutateRowTs(ByteBuffer tableName, ByteBuffer row,
955 List<Mutation> mutations, long timestamp,
956 Map<ByteBuffer, ByteBuffer> attributes)
957 throws IOError, IllegalArgument {
958 HTable table = null;
959 try {
960 table = getTable(tableName);
961 Put put = new Put(getBytes(row), timestamp);
962 addAttributes(put, attributes);
963
964 Delete delete = new Delete(getBytes(row));
965 addAttributes(delete, attributes);
966 if (metrics != null) {
967 metrics.incNumRowKeysInBatchMutate(mutations.size());
968 }
969
970
971 for (Mutation m : mutations) {
972 byte[][] famAndQf = KeyValue.parseColumn(getBytes(m.column));
973 if (m.isDelete) {
974 if (famAndQf.length == 1) {
975 delete.deleteFamily(famAndQf[0], timestamp);
976 } else {
977 delete.deleteColumns(famAndQf[0], famAndQf[1], timestamp);
978 }
979 delete.setWriteToWAL(m.writeToWAL);
980 } else {
981 if(famAndQf.length == 1) {
982 put.add(famAndQf[0], HConstants.EMPTY_BYTE_ARRAY,
983 m.value != null ? getBytes(m.value)
984 : HConstants.EMPTY_BYTE_ARRAY);
985 } else {
986 put.add(famAndQf[0], famAndQf[1],
987 m.value != null ? getBytes(m.value)
988 : HConstants.EMPTY_BYTE_ARRAY);
989 }
990 put.setWriteToWAL(m.writeToWAL);
991 }
992 }
993 if (!delete.isEmpty())
994 table.delete(delete);
995 if (!put.isEmpty())
996 table.put(put);
997 } catch (IOException e) {
998 LOG.warn(e.getMessage(), e);
999 throw new IOError(e.getMessage());
1000 } catch (IllegalArgumentException e) {
1001 LOG.warn(e.getMessage(), e);
1002 throw new IllegalArgument(e.getMessage());
1003 }
1004 }
1005
1006 @Override
1007 public void mutateRows(ByteBuffer tableName, List<BatchMutation> rowBatches,
1008 Map<ByteBuffer, ByteBuffer> attributes)
1009 throws IOError, IllegalArgument, TException {
1010 mutateRowsTs(tableName, rowBatches, HConstants.LATEST_TIMESTAMP, attributes);
1011 }
1012
1013 @Override
1014 public void mutateRowsTs(
1015 ByteBuffer tableName, List<BatchMutation> rowBatches, long timestamp,
1016 Map<ByteBuffer, ByteBuffer> attributes)
1017 throws IOError, IllegalArgument, TException {
1018 List<Put> puts = new ArrayList<Put>();
1019 List<Delete> deletes = new ArrayList<Delete>();
1020
1021 for (BatchMutation batch : rowBatches) {
1022 byte[] row = getBytes(batch.row);
1023 List<Mutation> mutations = batch.mutations;
1024 Delete delete = new Delete(row);
1025 addAttributes(delete, attributes);
1026 Put put = new Put(row, timestamp);
1027 addAttributes(put, attributes);
1028 for (Mutation m : mutations) {
1029 byte[][] famAndQf = KeyValue.parseColumn(getBytes(m.column));
1030 if (m.isDelete) {
1031
1032 if (famAndQf.length == 1) {
1033 delete.deleteFamily(famAndQf[0], timestamp);
1034 } else {
1035 delete.deleteColumns(famAndQf[0], famAndQf[1], timestamp);
1036 }
1037 delete.setWriteToWAL(m.writeToWAL);
1038 } else {
1039 if(famAndQf.length == 1) {
1040 put.add(famAndQf[0], HConstants.EMPTY_BYTE_ARRAY,
1041 m.value != null ? getBytes(m.value)
1042 : HConstants.EMPTY_BYTE_ARRAY);
1043 } else {
1044 put.add(famAndQf[0], famAndQf[1],
1045 m.value != null ? getBytes(m.value)
1046 : HConstants.EMPTY_BYTE_ARRAY);
1047 }
1048 put.setWriteToWAL(m.writeToWAL);
1049 }
1050 }
1051 if (!delete.isEmpty())
1052 deletes.add(delete);
1053 if (!put.isEmpty())
1054 puts.add(put);
1055 }
1056
1057 HTable table = null;
1058 try {
1059 table = getTable(tableName);
1060 if (!puts.isEmpty())
1061 table.put(puts);
1062 if (!deletes.isEmpty())
1063 table.delete(deletes);
1064
1065 } catch (IOException e) {
1066 LOG.warn(e.getMessage(), e);
1067 throw new IOError(e.getMessage());
1068 } catch (IllegalArgumentException e) {
1069 LOG.warn(e.getMessage(), e);
1070 throw new IllegalArgument(e.getMessage());
1071 }
1072 }
1073
1074 @Deprecated
1075 @Override
1076 public long atomicIncrement(
1077 ByteBuffer tableName, ByteBuffer row, ByteBuffer column, long amount)
1078 throws IOError, IllegalArgument, TException {
1079 byte [][] famAndQf = KeyValue.parseColumn(getBytes(column));
1080 if(famAndQf.length == 1) {
1081 return atomicIncrement(tableName, row, famAndQf[0], new byte[0],
1082 amount);
1083 }
1084 return atomicIncrement(tableName, row, famAndQf[0], famAndQf[1], amount);
1085 }
1086
1087 protected long atomicIncrement(ByteBuffer tableName, ByteBuffer row,
1088 byte [] family, byte [] qualifier, long amount)
1089 throws IOError, IllegalArgument, TException {
1090 HTable table;
1091 try {
1092 table = getTable(tableName);
1093 return table.incrementColumnValue(
1094 getBytes(row), family, qualifier, amount);
1095 } catch (IOException e) {
1096 LOG.warn(e.getMessage(), e);
1097 throw new IOError(e.getMessage());
1098 }
1099 }
1100
1101 public void scannerClose(int id) throws IOError, IllegalArgument {
1102 LOG.debug("scannerClose: id=" + id);
1103 ResultScanner scanner = getScanner(id);
1104 if (scanner == null) {
1105 String message = "scanner ID is invalid";
1106 LOG.warn(message);
1107 throw new IllegalArgument("scanner ID is invalid");
1108 }
1109 scanner.close();
1110 removeScanner(id);
1111 }
1112
1113 @Override
1114 public List<TRowResult> scannerGetList(int id,int nbRows)
1115 throws IllegalArgument, IOError {
1116 LOG.debug("scannerGetList: id=" + id);
1117 ResultScanner scanner = getScanner(id);
1118 if (null == scanner) {
1119 String message = "scanner ID is invalid";
1120 LOG.warn(message);
1121 throw new IllegalArgument("scanner ID is invalid");
1122 }
1123
1124 Result [] results = null;
1125 try {
1126 results = scanner.next(nbRows);
1127 if (null == results) {
1128 return new ArrayList<TRowResult>();
1129 }
1130 } catch (IOException e) {
1131 LOG.warn(e.getMessage(), e);
1132 throw new IOError(e.getMessage());
1133 }
1134 return ThriftUtilities.rowResultFromHBase(results);
1135 }
1136
1137 @Override
1138 public List<TRowResult> scannerGet(int id) throws IllegalArgument, IOError {
1139 return scannerGetList(id,1);
1140 }
1141
1142 public int scannerOpenWithScan(ByteBuffer tableName, TScan tScan,
1143 Map<ByteBuffer, ByteBuffer> attributes)
1144 throws IOError {
1145 try {
1146 HTable table = getTable(tableName);
1147 Scan scan = new Scan();
1148 addAttributes(scan, attributes);
1149 if (tScan.isSetStartRow()) {
1150 scan.setStartRow(tScan.getStartRow());
1151 }
1152 if (tScan.isSetStopRow()) {
1153 scan.setStopRow(tScan.getStopRow());
1154 }
1155 if (tScan.isSetTimestamp()) {
1156 scan.setTimeRange(Long.MIN_VALUE, tScan.getTimestamp());
1157 }
1158 if (tScan.isSetCaching()) {
1159 scan.setCaching(tScan.getCaching());
1160 }
1161 if (tScan.isSetColumns() && tScan.getColumns().size() != 0) {
1162 for(ByteBuffer column : tScan.getColumns()) {
1163 byte [][] famQf = KeyValue.parseColumn(getBytes(column));
1164 if(famQf.length == 1) {
1165 scan.addFamily(famQf[0]);
1166 } else {
1167 scan.addColumn(famQf[0], famQf[1]);
1168 }
1169 }
1170 }
1171 if (tScan.isSetFilterString()) {
1172 ParseFilter parseFilter = new ParseFilter();
1173 scan.setFilter(
1174 parseFilter.parseFilterString(tScan.getFilterString()));
1175 }
1176 return addScanner(table.getScanner(scan));
1177 } catch (IOException e) {
1178 LOG.warn(e.getMessage(), e);
1179 throw new IOError(e.getMessage());
1180 }
1181 }
1182
1183 @Override
1184 public int scannerOpen(ByteBuffer tableName, ByteBuffer startRow,
1185 List<ByteBuffer> columns,
1186 Map<ByteBuffer, ByteBuffer> attributes) throws IOError {
1187 try {
1188 HTable table = getTable(tableName);
1189 Scan scan = new Scan(getBytes(startRow));
1190 addAttributes(scan, attributes);
1191 if(columns != null && columns.size() != 0) {
1192 for(ByteBuffer column : columns) {
1193 byte [][] famQf = KeyValue.parseColumn(getBytes(column));
1194 if(famQf.length == 1) {
1195 scan.addFamily(famQf[0]);
1196 } else {
1197 scan.addColumn(famQf[0], famQf[1]);
1198 }
1199 }
1200 }
1201 return addScanner(table.getScanner(scan));
1202 } catch (IOException e) {
1203 LOG.warn(e.getMessage(), e);
1204 throw new IOError(e.getMessage());
1205 }
1206 }
1207
1208 @Override
1209 public int scannerOpenWithStop(ByteBuffer tableName, ByteBuffer startRow,
1210 ByteBuffer stopRow, List<ByteBuffer> columns,
1211 Map<ByteBuffer, ByteBuffer> attributes)
1212 throws IOError, TException {
1213 try {
1214 HTable table = getTable(tableName);
1215 Scan scan = new Scan(getBytes(startRow), getBytes(stopRow));
1216 addAttributes(scan, attributes);
1217 if(columns != null && columns.size() != 0) {
1218 for(ByteBuffer column : columns) {
1219 byte [][] famQf = KeyValue.parseColumn(getBytes(column));
1220 if(famQf.length == 1) {
1221 scan.addFamily(famQf[0]);
1222 } else {
1223 scan.addColumn(famQf[0], famQf[1]);
1224 }
1225 }
1226 }
1227 return addScanner(table.getScanner(scan));
1228 } catch (IOException e) {
1229 LOG.warn(e.getMessage(), e);
1230 throw new IOError(e.getMessage());
1231 }
1232 }
1233
1234 @Override
1235 public int scannerOpenWithPrefix(ByteBuffer tableName,
1236 ByteBuffer startAndPrefix,
1237 List<ByteBuffer> columns,
1238 Map<ByteBuffer, ByteBuffer> attributes)
1239 throws IOError, TException {
1240 try {
1241 HTable table = getTable(tableName);
1242 Scan scan = new Scan(getBytes(startAndPrefix));
1243 addAttributes(scan, attributes);
1244 Filter f = new WhileMatchFilter(
1245 new PrefixFilter(getBytes(startAndPrefix)));
1246 scan.setFilter(f);
1247 if (columns != null && columns.size() != 0) {
1248 for(ByteBuffer column : columns) {
1249 byte [][] famQf = KeyValue.parseColumn(getBytes(column));
1250 if(famQf.length == 1) {
1251 scan.addFamily(famQf[0]);
1252 } else {
1253 scan.addColumn(famQf[0], famQf[1]);
1254 }
1255 }
1256 }
1257 return addScanner(table.getScanner(scan));
1258 } catch (IOException e) {
1259 LOG.warn(e.getMessage(), e);
1260 throw new IOError(e.getMessage());
1261 }
1262 }
1263
1264 @Override
1265 public int scannerOpenTs(ByteBuffer tableName, ByteBuffer startRow,
1266 List<ByteBuffer> columns, long timestamp,
1267 Map<ByteBuffer, ByteBuffer> attributes) throws IOError, TException {
1268 try {
1269 HTable table = getTable(tableName);
1270 Scan scan = new Scan(getBytes(startRow));
1271 addAttributes(scan, attributes);
1272 scan.setTimeRange(Long.MIN_VALUE, timestamp);
1273 if (columns != null && columns.size() != 0) {
1274 for (ByteBuffer column : columns) {
1275 byte [][] famQf = KeyValue.parseColumn(getBytes(column));
1276 if(famQf.length == 1) {
1277 scan.addFamily(famQf[0]);
1278 } else {
1279 scan.addColumn(famQf[0], famQf[1]);
1280 }
1281 }
1282 }
1283 return addScanner(table.getScanner(scan));
1284 } catch (IOException e) {
1285 LOG.warn(e.getMessage(), e);
1286 throw new IOError(e.getMessage());
1287 }
1288 }
1289
1290 @Override
1291 public int scannerOpenWithStopTs(ByteBuffer tableName, ByteBuffer startRow,
1292 ByteBuffer stopRow, List<ByteBuffer> columns, long timestamp,
1293 Map<ByteBuffer, ByteBuffer> attributes)
1294 throws IOError, TException {
1295 try {
1296 HTable table = getTable(tableName);
1297 Scan scan = new Scan(getBytes(startRow), getBytes(stopRow));
1298 addAttributes(scan, attributes);
1299 scan.setTimeRange(Long.MIN_VALUE, timestamp);
1300 if (columns != null && columns.size() != 0) {
1301 for (ByteBuffer column : columns) {
1302 byte [][] famQf = KeyValue.parseColumn(getBytes(column));
1303 if(famQf.length == 1) {
1304 scan.addFamily(famQf[0]);
1305 } else {
1306 scan.addColumn(famQf[0], famQf[1]);
1307 }
1308 }
1309 }
1310 scan.setTimeRange(Long.MIN_VALUE, timestamp);
1311 return addScanner(table.getScanner(scan));
1312 } catch (IOException e) {
1313 LOG.warn(e.getMessage(), e);
1314 throw new IOError(e.getMessage());
1315 }
1316 }
1317
1318 @Override
1319 public Map<ByteBuffer, ColumnDescriptor> getColumnDescriptors(
1320 ByteBuffer tableName) throws IOError, TException {
1321 try {
1322 TreeMap<ByteBuffer, ColumnDescriptor> columns =
1323 new TreeMap<ByteBuffer, ColumnDescriptor>();
1324
1325 HTable table = getTable(tableName);
1326 HTableDescriptor desc = table.getTableDescriptor();
1327
1328 for (HColumnDescriptor e : desc.getFamilies()) {
1329 ColumnDescriptor col = ThriftUtilities.colDescFromHbase(e);
1330 columns.put(col.name, col);
1331 }
1332 return columns;
1333 } catch (IOException e) {
1334 LOG.warn(e.getMessage(), e);
1335 throw new IOError(e.getMessage());
1336 }
1337 }
1338
1339 @Override
1340 public List<TCell> getRowOrBefore(ByteBuffer tableName, ByteBuffer row,
1341 ByteBuffer family) throws IOError {
1342 try {
1343 HTable table = getTable(getBytes(tableName));
1344 Result result = table.getRowOrBefore(getBytes(row), getBytes(family));
1345 return ThriftUtilities.cellFromHBase(result.raw());
1346 } catch (IOException e) {
1347 LOG.warn(e.getMessage(), e);
1348 throw new IOError(e.getMessage());
1349 }
1350 }
1351
1352 @Override
1353 public TRegionInfo getRegionInfo(ByteBuffer searchRow) throws IOError {
1354 try {
1355 HTable table = getTable(HConstants.META_TABLE_NAME);
1356 byte[] row = getBytes(searchRow);
1357 Result startRowResult = table.getRowOrBefore(
1358 row, HConstants.CATALOG_FAMILY);
1359
1360 if (startRowResult == null) {
1361 throw new IOException("Cannot find row in .META., row="
1362 + Bytes.toStringBinary(row));
1363 }
1364
1365
1366 HRegionInfo regionInfo = HRegionInfo.getHRegionInfo(startRowResult);
1367 if (regionInfo == null) {
1368 throw new IOException("HRegionInfo REGIONINFO was null or " +
1369 " empty in Meta for row="
1370 + Bytes.toStringBinary(row));
1371 }
1372 TRegionInfo region = new TRegionInfo();
1373 region.setStartKey(regionInfo.getStartKey());
1374 region.setEndKey(regionInfo.getEndKey());
1375 region.id = regionInfo.getRegionId();
1376 region.setName(regionInfo.getRegionName());
1377 region.version = regionInfo.getVersion();
1378
1379
1380 ServerName serverName = HRegionInfo.getServerName(startRowResult);
1381 if (serverName != null) {
1382 region.setServerName(Bytes.toBytes(serverName.getHostname()));
1383 region.port = serverName.getPort();
1384 }
1385 return region;
1386 } catch (IOException e) {
1387 LOG.warn(e.getMessage(), e);
1388 throw new IOError(e.getMessage());
1389 }
1390 }
1391
1392 private void initMetrics(ThriftMetrics metrics) {
1393 this.metrics = metrics;
1394 }
1395
1396 @Override
1397 public void increment(TIncrement tincrement) throws IOError, TException {
1398
1399 if (tincrement.getRow().length == 0 || tincrement.getTable().length == 0) {
1400 throw new TException("Must supply a table and a row key; can't increment");
1401 }
1402
1403 if (conf.getBoolean(COALESCE_INC_KEY, false)) {
1404 this.coalescer.queueIncrement(tincrement);
1405 return;
1406 }
1407
1408 try {
1409 HTable table = getTable(tincrement.getTable());
1410 Increment inc = ThriftUtilities.incrementFromThrift(tincrement);
1411 table.increment(inc);
1412 } catch (IOException e) {
1413 LOG.warn(e.getMessage(), e);
1414 throw new IOError(e.getMessage());
1415 }
1416 }
1417
1418 @Override
1419 public void incrementRows(List<TIncrement> tincrements) throws IOError, TException {
1420 if (conf.getBoolean(COALESCE_INC_KEY, false)) {
1421 this.coalescer.queueIncrements(tincrements);
1422 return;
1423 }
1424 for (TIncrement tinc : tincrements) {
1425 increment(tinc);
1426 }
1427 }
1428 }
1429
1430
1431
1432
1433
1434
1435 private static void addAttributes(OperationWithAttributes op,
1436 Map<ByteBuffer, ByteBuffer> attributes) {
1437 if (attributes == null || attributes.size() == 0) {
1438 return;
1439 }
1440 for (Map.Entry<ByteBuffer, ByteBuffer> entry : attributes.entrySet()) {
1441 String name = Bytes.toStringBinary(getBytes(entry.getKey()));
1442 byte[] value = getBytes(entry.getValue());
1443 op.setAttribute(name, value);
1444 }
1445 }
1446
1447 public static void registerFilters(Configuration conf) {
1448 String[] filters = conf.getStrings("hbase.thrift.filters");
1449 if(filters != null) {
1450 for(String filterClass: filters) {
1451 String[] filterPart = filterClass.split(":");
1452 if(filterPart.length != 2) {
1453 LOG.warn("Invalid filter specification " + filterClass + " - skipping");
1454 } else {
1455 ParseFilter.registerFilter(filterPart[0], filterPart[1]);
1456 }
1457 }
1458 }
1459 }
1460 }