3 # Licensed to the Apache Software Foundation (ASF) under one
4 # or more contributor license agreements. See the NOTICE file
5 # distributed with this work for additional information
6 # regarding copyright ownership. The ASF licenses this file
7 # to you under the Apache License, Version 2.0 (the
8 # "License"); you may not use this file except in compliance
9 # with the License. You may obtain a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
22 java_import org.apache.hadoop.hbase.util.Bytes
23 java_import org.apache.hadoop.hbase.client.RegionReplicaUtil
25 # Wrapper for org.apache.hadoop.hbase.client.Table
28 # rubocop:disable Metrics/ClassLength
30 include HBaseConstants
33 # Add the command 'name' to table s.t. the shell command also called via 'name'
34 # and has an internal method also called 'name'.
36 # e.g. name = scan, adds table.scan which calls Scan.scan
37 def self.add_shell_command(name)
38 add_command(name, name, name)
41 # add a named command to the table instance
43 # name - name of the command that should added to the table
44 # (eg. sending 'scan' here would allow you to do table.scan)
45 # shell_command - name of the command in the shell
46 # internal_method_name - name of the method in the shell command to forward the call
47 def self.add_command(name, shell_command, internal_method_name)
50 define_method method do |*args|
51 @shell.internal_command(shell_command, internal_method_name, self, *args)
56 # General help for the table
57 # class level so we can call it from anywhere
60 Help for table-reference commands.
62 You can either create a table via 'create' and then manipulate the table via commands like 'put', 'get', etc.
63 See the standard help information for how to use each of these commands.
65 However, as of 0.96, you can also get a reference to a table, on which you can invoke commands.
66 For instance, you can get create a table and keep around a reference to it via:
68 hbase> t = create 't', 'cf'
70 Or, if you have already created the table, you can get a reference to it:
72 hbase> t = get_table 't'
74 You can do things like call 'put' on the table:
76 hbase> t.put 'r', 'cf:q', 'v'
78 which puts a row 'r' with column family 'cf', qualifier 'q' and value 'v' into table t.
80 To read the data out, you can scan the table:
84 which will read all the rows in table 't'.
86 Essentially, any command that takes a table name can also be done via table reference.
87 Other commands include things like: get, delete, deleteall,
88 get_all_columns, get_counter, count, incr. These functions, along with
89 the standard JRuby object methods are also available via tab completion.
91 For more information on how to use each of these commands, you can also just type:
95 which will output more information on how to use that command.
97 You can also do general admin actions directly on a table; things like enable, disable,
98 flush and drop just by typing:
105 Note that after dropping a table, your reference to it becomes useless and further usage
106 is undefined (and not recommended).
110 #---------------------------------------------------------------------------------------------
112 # let external objects read the underlying table object
114 # let external objects read the table name
117 def initialize(table, shell)
119 @name = @table.getName.getNameAsString
128 # Note the below methods are prefixed with '_' to hide them from the average user, as
129 # they will be much less likely to tab complete to the 'dangerous' internal method
130 #----------------------------------------------------------------------------------------------
132 # Put a cell 'value' at specified table/row/column
133 def _put_internal(row, column, value, timestamp = nil, args = {})
134 p = org.apache.hadoop.hbase.client.Put.new(row.to_s.to_java_bytes)
135 family, qualifier = parse_column_name(column)
137 attributes = args[ATTRIBUTES]
138 set_attributes(p, attributes) if attributes
139 visibility = args[VISIBILITY]
140 set_cell_visibility(p, visibility) if visibility
142 set_op_ttl(p, ttl) if ttl
144 # Case where attributes are specified without timestamp
145 if timestamp.is_a?(Hash)
146 timestamp.each do |k, v|
149 elsif k == 'VISIBILITY'
150 set_cell_visibility(p, v)
158 p.addColumn(family, qualifier, timestamp, value.to_s.to_java_bytes)
160 p.addColumn(family, qualifier, value.to_s.to_java_bytes)
165 #----------------------------------------------------------------------------------------------
166 # Create a Delete mutation
167 def _createdelete_internal(row, column = nil,
168 timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP,
169 args = {}, all_version = true)
170 temptimestamp = timestamp
171 if temptimestamp.is_a?(Hash)
172 timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP
174 d = org.apache.hadoop.hbase.client.Delete.new(row.to_s.to_java_bytes, timestamp)
175 if temptimestamp.is_a?(Hash)
176 temptimestamp.each do |_k, v|
178 set_cell_visibility(d, v) if v
183 visibility = args[VISIBILITY]
184 set_cell_visibility(d, visibility) if visibility
186 if column && all_version
187 family, qualifier = parse_column_name(column)
188 d.addColumns(family, qualifier, timestamp)
189 elsif column && !all_version
190 family, qualifier = parse_column_name(column)
191 d.addColumn(family, qualifier, timestamp)
196 #----------------------------------------------------------------------------------------------
197 # Delete rows using prefix
198 def _deleterows_internal(row, column = nil,
199 timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP,
200 args = {}, all_version = true)
201 cache = row['CACHE'] ? row['CACHE'] : 100
202 prefix = row['ROWPREFIXFILTER']
204 # create scan to get table names using prefix
205 scan = org.apache.hadoop.hbase.client.Scan.new
206 scan.setRowPrefixFilter(prefix.to_java_bytes)
207 # Run the scanner to get all rowkeys
208 scanner = @table.getScanner(scan)
209 # Create a list to store all deletes
210 list = java.util.ArrayList.new
212 iter = scanner.iterator
215 key = org.apache.hadoop.hbase.util.Bytes.toStringBinary(row.getRow)
216 d = _createdelete_internal(key, column, timestamp, args, all_version)
218 if list.size >= cache
226 #----------------------------------------------------------------------------------------------
228 def _delete_internal(row, column,
229 timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP,
230 args = {}, all_version = false)
231 _deleteall_internal(row, column, timestamp, args, all_version)
234 #----------------------------------------------------------------------------------------------
236 def _deleteall_internal(row, column = nil,
237 timestamp = org.apache.hadoop.hbase.HConstants::LATEST_TIMESTAMP,
238 args = {}, all_version = true)
239 # delete operation doesn't need read permission. Retaining the read check for
240 # meta table as a part of HBASE-5837.
242 raise ArgumentError, 'Row Not Found' if _get_internal(row).nil?
245 _deleterows_internal(row, column, timestamp, args, all_version)
247 d = _createdelete_internal(row, column, timestamp, args, all_version)
252 #----------------------------------------------------------------------------------------------
253 # Increment a counter atomically
254 # rubocop:disable Metrics/AbcSize, CyclomaticComplexity, MethodLength
255 def _incr_internal(row, column, value = nil, args = {})
256 value = 1 if value.is_a?(Hash)
258 incr = org.apache.hadoop.hbase.client.Increment.new(row.to_s.to_java_bytes)
259 family, qualifier = parse_column_name(column)
261 attributes = args[ATTRIBUTES]
262 visibility = args[VISIBILITY]
263 set_attributes(incr, attributes) if attributes
264 set_cell_visibility(incr, visibility) if visibility
266 set_op_ttl(incr, ttl) if ttl
268 incr.addColumn(family, qualifier, value)
269 result = @table.increment(incr)
270 return nil if result.isEmpty
273 cell = result.listCells[0]
274 org.apache.hadoop.hbase.util.Bytes.toLong(cell.getValueArray,
275 cell.getValueOffset, cell.getValueLength)
278 #----------------------------------------------------------------------------------------------
279 # appends the value atomically
280 def _append_internal(row, column, value, args = {})
281 append = org.apache.hadoop.hbase.client.Append.new(row.to_s.to_java_bytes)
282 family, qualifier = parse_column_name(column)
284 attributes = args[ATTRIBUTES]
285 visibility = args[VISIBILITY]
286 set_attributes(append, attributes) if attributes
287 set_cell_visibility(append, visibility) if visibility
289 set_op_ttl(append, ttl) if ttl
291 append.addColumn(family, qualifier, value.to_s.to_java_bytes)
292 result = @table.append(append)
293 return nil if result.isEmpty
296 cell = result.listCells[0]
297 org.apache.hadoop.hbase.util.Bytes.toStringBinary(cell.getValueArray,
298 cell.getValueOffset, cell.getValueLength)
300 # rubocop:enable Metrics/AbcSize, CyclomaticComplexity, MethodLength
302 #----------------------------------------------------------------------------------------------
303 # Count rows in a table
304 def _count_internal(interval = 1000, scan = nil)
305 raise(ArgumentError, 'Scan argument should be org.apache.hadoop.hbase.client.Scan') \
306 unless scan.nil? || scan.is_a?(org.apache.hadoop.hbase.client.Scan)
307 # We can safely set scanner caching with the first key only filter
310 scan = org.apache.hadoop.hbase.client.Scan.new
311 scan.setCacheBlocks(false)
313 scan.setFilter(org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter.new)
315 scan.setCacheBlocks(false)
316 filter = scan.getFilter
317 firstKeyOnlyFilter = org.apache.hadoop.hbase.filter.FirstKeyOnlyFilter.new
319 scan.setFilter(firstKeyOnlyFilter)
321 firstKeyOnlyFilter.setReversed(filter.isReversed)
322 scan.setFilter(org.apache.hadoop.hbase.filter.FilterList.new(filter, firstKeyOnlyFilter))
327 scanner = @table.getScanner(scan)
329 iter = scanner.iterator
335 next unless block_given? && count % interval == 0
336 # Allow command modules to visualize counting process
338 org.apache.hadoop.hbase.util.Bytes.toStringBinary(row.getRow))
346 #----------------------------------------------------------------------------------------------
348 def _get_internal(row, *args)
349 get = org.apache.hadoop.hbase.client.Get.new(row.to_s.to_java_bytes)
355 args = args.first if args.first.is_a?(Hash)
356 if args.is_a?(String) || args.is_a?(Array)
357 columns = [args].flatten.compact
358 args = { COLUMNS => columns }
364 unless args.is_a?(Hash)
365 raise ArgumentError, "Failed parse of #{args.inspect}, #{args.class}"
368 # Get maxlength parameter if passed
369 maxlength = args.delete(MAXLENGTH) if args[MAXLENGTH]
370 filter = args.delete(FILTER) if args[FILTER]
371 attributes = args[ATTRIBUTES]
372 authorizations = args[AUTHORIZATIONS]
373 consistency = args.delete(CONSISTENCY) if args[CONSISTENCY]
374 replicaId = args.delete(REGION_REPLICA_ID) if args[REGION_REPLICA_ID]
375 converter = args.delete(FORMATTER) || nil
376 converter_class = args.delete(FORMATTER_CLASS) || 'org.apache.hadoop.hbase.util.Bytes'
378 columns = args[COLUMN] || args[COLUMNS]
379 vers = if args[VERSIONS]
385 # Normalize types, convert string to an array of strings
386 columns = [columns] if columns.is_a?(String)
388 # At this point it is either an array or some unsupported stuff
389 unless columns.is_a?(Array)
390 raise ArgumentError, "Failed parse column argument type #{args.inspect}, #{args.class}"
393 # Get each column name and add it to the filter
394 columns.each do |column|
395 family, qualifier = parse_column_name(column.to_s)
397 get.addColumn(family, qualifier)
399 get.addFamily(family)
404 get.readVersions(vers)
405 get.setTimestamp(args[TIMESTAMP]) if args[TIMESTAMP]
406 get.setTimeRange(args[TIMERANGE][0], args[TIMERANGE][1]) if args[TIMERANGE]
409 set_attributes(get, attributes)
411 set_authorizations(get, authorizations)
413 # May have passed TIMESTAMP and row only; wants all columns from ts.
414 unless ts = args[TIMESTAMP] || tr = args[TIMERANGE]
415 raise ArgumentError, "Failed parse of #{args.inspect}, #{args.class}"
419 get.readVersions(vers)
420 # Set the timestamp/timerange
421 get.setTimestamp(ts.to_i) if args[TIMESTAMP]
422 get.setTimeRange(args[TIMERANGE][0], args[TIMERANGE][1]) if args[TIMERANGE]
424 set_attributes(get, attributes) if attributes
425 set_authorizations(get, authorizations) if authorizations
428 if filter.class == String
430 org.apache.hadoop.hbase.filter.ParseFilter.new.parseFilterString(filter.to_java_bytes)
433 get.setFilter(filter)
436 get.setConsistency(org.apache.hadoop.hbase.client.Consistency.valueOf(consistency)) if consistency
437 get.setReplicaId(replicaId) if replicaId
439 # Call hbase for the results
440 result = @table.get(get)
441 return nil if result.isEmpty
443 # Get stale info from results
444 is_stale = result.isStale
447 # Print out results. Result can be Cell or RowResult.
449 result.listCells.each do |c|
450 family = convert_bytes_with_position(c.getFamilyArray,
451 c.getFamilyOffset, c.getFamilyLength, converter_class, converter)
452 qualifier = convert_bytes_with_position(c.getQualifierArray,
453 c.getQualifierOffset, c.getQualifierLength, converter_class, converter)
455 column = "#{family}:#{qualifier}"
456 value = to_string(column, c, maxlength, converter_class, converter)
465 # If block given, we've yielded all the results, otherwise just return them
466 (block_given? ? [count, is_stale] : res)
469 #----------------------------------------------------------------------------------------------
470 # Fetches and decodes a counter value from hbase
471 def _get_counter_internal(row, column)
472 family, qualifier = parse_column_name(column.to_s)
474 get = org.apache.hadoop.hbase.client.Get.new(row.to_s.to_java_bytes)
475 get.addColumn(family, qualifier)
479 result = @table.get(get)
480 return nil if result.isEmpty
483 cell = result.listCells[0]
484 org.apache.hadoop.hbase.util.Bytes.toLong(cell.getValueArray,
485 cell.getValueOffset, cell.getValueLength)
488 def _hash_to_scan(args)
490 enablemetrics = args['ALL_METRICS'].nil? ? false : args['ALL_METRICS']
491 enablemetrics ||= !args['METRICS'].nil?
492 filter = args['FILTER']
493 startrow = args['STARTROW'] || ''
494 stoprow = args['STOPROW']
495 rowprefixfilter = args['ROWPREFIXFILTER']
496 timestamp = args['TIMESTAMP']
497 columns = args['COLUMNS'] || args['COLUMN'] || []
498 # If CACHE_BLOCKS not set, then default 'true'.
499 cache_blocks = args['CACHE_BLOCKS'].nil? ? true : args['CACHE_BLOCKS']
500 cache = args['CACHE'] || 0
501 reversed = args['REVERSED'] || false
502 versions = args['VERSIONS'] || 1
503 timerange = args[TIMERANGE]
504 raw = args['RAW'] || false
505 attributes = args[ATTRIBUTES]
506 authorizations = args[AUTHORIZATIONS]
507 consistency = args[CONSISTENCY]
508 # Normalize column names
509 columns = [columns] if columns.class == String
510 limit = args['LIMIT'] || -1
511 replica_id = args[REGION_REPLICA_ID]
512 isolation_level = args[ISOLATION_LEVEL]
513 read_type = args[READ_TYPE]
514 allow_partial_results = args[ALLOW_PARTIAL_RESULTS].nil? ? false : args[ALLOW_PARTIAL_RESULTS]
515 batch = args[BATCH] || -1
516 max_result_size = args[MAX_RESULT_SIZE] || -1
518 unless columns.is_a?(Array)
519 raise ArgumentError, 'COLUMNS must be specified as a String or an Array'
523 org.apache.hadoop.hbase.client.Scan.new(startrow.to_java_bytes, stoprow.to_java_bytes)
525 org.apache.hadoop.hbase.client.Scan.new(startrow.to_java_bytes)
528 # This will overwrite any startrow/stoprow settings
529 scan.setRowPrefixFilter(rowprefixfilter.to_java_bytes) if rowprefixfilter
531 # Clear converters from last scan.
535 family, qualifier = parse_column_name(c.to_s)
537 scan.addColumn(family, qualifier)
539 scan.addFamily(family)
543 if filter.class == String
545 org.apache.hadoop.hbase.filter.ParseFilter.new.parseFilterString(filter.to_java_bytes)
548 scan.setFilter(filter)
551 scan.setScanMetricsEnabled(enablemetrics) if enablemetrics
552 scan.setTimeStamp(timestamp) if timestamp
553 scan.setCacheBlocks(cache_blocks)
554 scan.setReversed(reversed)
555 scan.setCaching(cache) if cache > 0
556 scan.readVersions(versions) if versions > 1
557 scan.setTimeRange(timerange[0], timerange[1]) if timerange
559 scan.setLimit(limit) if limit > 0
560 set_attributes(scan, attributes) if attributes
561 set_authorizations(scan, authorizations) if authorizations
562 scan.setConsistency(org.apache.hadoop.hbase.client.Consistency.valueOf(consistency)) if consistency
563 scan.setReplicaId(replica_id) if replica_id
564 scan.setIsolationLevel(org.apache.hadoop.hbase.client.IsolationLevel.valueOf(isolation_level)) if isolation_level
565 scan.setReadType(org.apache.hadoop.hbase.client::Scan::ReadType.valueOf(read_type)) if read_type
566 scan.setAllowPartialResults(allow_partial_results) if allow_partial_results
567 scan.setBatch(batch) if batch > 0
568 scan.setMaxResultSize(max_result_size) if max_result_size > 0
570 scan = org.apache.hadoop.hbase.client.Scan.new
576 def _get_scanner(args)
577 @table.getScanner(_hash_to_scan(args))
580 #----------------------------------------------------------------------------------------------
581 # Scans whole table or a range of keys and returns rows matching specific criteria
582 def _scan_internal(args = {}, scan = nil)
583 raise(ArgumentError, 'Args should be a Hash') unless args.is_a?(Hash)
584 raise(ArgumentError, 'Scan argument should be org.apache.hadoop.hbase.client.Scan') \
585 unless scan.nil? || scan.is_a?(org.apache.hadoop.hbase.client.Scan)
587 maxlength = args.delete('MAXLENGTH') || -1
588 converter = args.delete(FORMATTER) || nil
589 converter_class = args.delete(FORMATTER_CLASS) || 'org.apache.hadoop.hbase.util.Bytes'
594 scan = scan.nil? ? _hash_to_scan(args) : scan
595 scanner = @table.getScanner(scan)
596 iter = scanner.iterator
601 key = convert_bytes(row.getRow, nil, converter)
602 is_stale |= row.isStale
604 row.listCells.each do |c|
605 family = convert_bytes_with_position(c.getFamilyArray,
606 c.getFamilyOffset, c.getFamilyLength, converter_class, converter)
607 qualifier = convert_bytes_with_position(c.getQualifierArray,
608 c.getQualifierOffset, c.getQualifierLength, converter_class, converter)
610 column = "#{family}:#{qualifier}"
611 cell = to_string(column, c, maxlength, converter_class, converter)
614 yield(key, "column=#{column}, #{cell}")
617 res[key][column] = cell
620 # One more row processed
625 (block_given? ? [count, is_stale] : res)
628 # Apply OperationAttributes to puts/scans/gets
629 def set_attributes(oprattr, attributes)
630 raise(ArgumentError, 'Attributes must be a Hash type') unless attributes.is_a?(Hash)
631 for k, v in attributes
632 v = v.to_s unless v.nil?
633 oprattr.setAttribute(k.to_s, v.to_java_bytes)
637 def set_cell_permissions(op, permissions)
638 raise(ArgumentError, 'Permissions must be a Hash type') unless permissions.is_a?(Hash)
639 map = java.util.HashMap.new
640 permissions.each do |user, perms|
641 map.put(user.to_s, org.apache.hadoop.hbase.security.access.Permission.new(
648 def set_cell_visibility(oprattr, visibility)
649 oprattr.setCellVisibility(
650 org.apache.hadoop.hbase.security.visibility.CellVisibility.new(
656 def set_authorizations(oprattr, authorizations)
657 raise(ArgumentError, 'Authorizations must be a Array type') unless authorizations.is_a?(Array)
658 auths = [authorizations].flatten.compact
659 oprattr.setAuthorizations(
660 org.apache.hadoop.hbase.security.visibility.Authorizations.new(
661 auths.to_java(:string)
666 def set_op_ttl(op, ttl)
667 op.setTTL(ttl.to_java(:long))
670 #----------------------------
671 # Add general administration utilities to the shell
672 # each of the names below adds this method name to the table
673 # by callling the corresponding method in the shell
674 # Add single method utilities to the current class
675 # Generally used for admin functions which just have one name and take the table name
676 def self.add_admin_utils(*args)
677 args.each do |method|
678 define_method method do |*method_args|
679 @shell.command(method, @name, *method_args)
684 # Add the following admin utilities to the table
685 add_admin_utils :enable, :disable, :flush, :drop, :describe, :snapshot
687 #----------------------------
688 # give the general help for the table
689 # or the named command
690 def help(command = nil)
691 # if there is a command, get the per-command help from the shell
694 return @shell.help_command(command)
696 puts "Command \'#{command}\' does not exist. Please see general table help."
700 @shell.help('table_help')
709 # Standard ruby call to get the return value for an object
710 # overriden here so we get sane semantics for printing a table on return
715 #----------------------------------------------------------------------------------------
718 # Returns a list of column names in the table
720 @table.descriptor.getColumnFamilies.map do |family|
721 "#{family.getNameAsString}:"
725 # Checks if current table is one of the 'meta' tables
727 org.apache.hadoop.hbase.TableName::META_TABLE_NAME.equals(@table.getName)
730 # Returns family and (when has it) qualifier for a column name
731 def parse_column_name(column)
732 split = org.apache.hadoop.hbase.CellUtil.parseColumn(column.to_java_bytes)
733 set_converter(split) if split.length > 1
734 [split[0], split.length > 1 ? split[1] : nil]
737 # Make a String of the passed kv
738 # Intercept cells whose format we know such as the info:regioninfo in hbase:meta
739 def to_string(column, kv, maxlength = -1, converter_class = nil, converter = nil)
741 if column == 'info:regioninfo' || column == 'info:splitA' || column == 'info:splitB'
742 hri = org.apache.hadoop.hbase.HRegionInfo.parseFromOrNull(kv.getValueArray,
743 kv.getValueOffset, kv.getValueLength)
744 return format('timestamp=%d, value=%s', kv.getTimestamp, hri.nil? ? '' : hri.toString)
746 if column == 'info:serverstartcode'
747 if kv.getValueLength > 0
748 str_val = org.apache.hadoop.hbase.util.Bytes.toLong(kv.getValueArray,
749 kv.getValueOffset, kv.getValueLength)
751 str_val = org.apache.hadoop.hbase.util.Bytes.toStringBinary(kv.getValueArray,
752 kv.getValueOffset, kv.getValueLength)
754 return format('timestamp=%d, value=%s', kv.getTimestamp, str_val)
758 if org.apache.hadoop.hbase.CellUtil.isDelete(kv)
759 val = "timestamp=#{kv.getTimestamp}, type=#{org.apache.hadoop.hbase.KeyValue::Type.codeToType(kv.getTypeByte)}"
761 val = "timestamp=#{kv.getTimestamp}, value=#{convert(column, kv, converter_class, converter)}"
763 maxlength != -1 ? val[0, maxlength] : val
766 def convert(column, kv, converter_class = 'org.apache.hadoop.hbase.util.Bytes', converter = 'toStringBinary')
767 # use org.apache.hadoop.hbase.util.Bytes as the default class
768 converter_class = 'org.apache.hadoop.hbase.util.Bytes' unless converter_class
769 # use org.apache.hadoop.hbase.util.Bytes::toStringBinary as the default convertor
770 converter = 'toStringBinary' unless converter
771 if @converters.key?(column)
772 # lookup the CONVERTER for certain column - "cf:qualifier"
773 matches = /c\((.+)\)\.(.+)/.match(@converters[column])
775 # cannot match the pattern of 'c(className).functionname'
776 # use the default klazz_name
777 converter = @converters[column]
779 klazz_name = matches[1]
780 converter = matches[2]
783 # apply the converter
784 convert_bytes(org.apache.hadoop.hbase.CellUtil.cloneValue(kv), klazz_name, converter)
787 def convert_bytes(bytes, converter_class = nil, converter_method = nil)
789 converter_class ||= 'org.apache.hadoop.hbase.util.Bytes'
790 converter_method ||= 'toStringBinary'
791 eval(converter_class).method(converter_method).call(bytes)
794 def convert_bytes_with_position(bytes, offset, len, converter_class, converter_method)
796 converter_class ||= 'org.apache.hadoop.hbase.util.Bytes'
797 converter_method ||= 'toStringBinary'
798 eval(converter_class).method(converter_method).call(bytes, offset, len)
801 # if the column spec contains CONVERTER information, to get rid of :CONVERTER info from column pair.
802 # 1. return back normal column pair as usual, i.e., "cf:qualifier[:CONVERTER]" to "cf" and "qualifier" only
803 # 2. register the CONVERTER information based on column spec - "cf:qualifier"
804 def set_converter(column)
805 family = String.from_java_bytes(column[0])
806 parts = org.apache.hadoop.hbase.CellUtil.parseColumn(column[1])
808 @converters["#{family}:#{String.from_java_bytes(parts[0])}"] = String.from_java_bytes(parts[1])
813 #----------------------------------------------------------------------------------------------
814 # Get the split points for the table
815 def _get_splits_internal
816 locator = @table.getRegionLocator
817 locator.getAllRegionLocations
818 .select { |s| RegionReplicaUtil.isDefaultReplica(s.getRegion) }
819 .map { |i| Bytes.toStringBinary(i.getRegion.getStartKey) }
820 .delete_if { |k| k == '' }
825 # rubocop:enable Metrics/ClassLength