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