hbase-jruby 0.2.4-java → 0.2.5-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.md +8 -0
- data/README.md +205 -189
- data/lib/hbase-jruby/cell.rb +19 -1
- data/lib/hbase-jruby/dependency.rb +2 -2
- data/lib/hbase-jruby/hbase.rb +11 -0
- data/lib/hbase-jruby/pom/pom.xml.erb +1 -1
- data/lib/hbase-jruby/{result.rb → row.rb} +5 -2
- data/lib/hbase-jruby/scoped.rb +7 -7
- data/lib/hbase-jruby/table/admin.rb +15 -0
- data/lib/hbase-jruby/table.rb +1 -1
- data/lib/hbase-jruby/version.rb +1 -1
- data/lib/hbase-jruby.rb +1 -1
- data/test/test_cell.rb +16 -8
- data/test/test_table_admin.rb +32 -0
- metadata +3 -3
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
+
0.2.5
|
5
|
+
-----
|
6
|
+
- Added `HBase::Table#snapshots` method
|
7
|
+
- Added `HBase::Table#snapshot!` method
|
8
|
+
- Added `HBase#snapshots` method
|
9
|
+
- Added `HBase::Cell#{raw,int,short,byte}` methods
|
10
|
+
- Updated dependency profiles: cdh4.2.1, cdh4.1.4
|
11
|
+
|
4
12
|
0.2.4
|
5
13
|
-----
|
6
14
|
- Fixed NameError when HBase::ByteArray is used without first creating an HBase instance
|
data/README.md
CHANGED
@@ -147,14 +147,9 @@ table = hbase.table(:test_table)
|
|
147
147
|
table = hbase[:test_table]
|
148
148
|
```
|
149
149
|
|
150
|
-
|
151
|
-
## Basic table administration
|
152
|
-
|
153
150
|
### Creating a table
|
154
151
|
|
155
152
|
```ruby
|
156
|
-
table = hbase[:my_table]
|
157
|
-
|
158
153
|
# Drop table if exists
|
159
154
|
table.drop! if table.exists?
|
160
155
|
|
@@ -163,80 +158,6 @@ table.create! :cf1 => {},
|
|
163
158
|
:cf2 => { :compression => :snappy, :bloomfilter => :row }
|
164
159
|
```
|
165
160
|
|
166
|
-
### Table inspection
|
167
|
-
|
168
|
-
```ruby
|
169
|
-
# Table properties
|
170
|
-
table.properties
|
171
|
-
# {:max_filesize => 2147483648,
|
172
|
-
# :readonly => false,
|
173
|
-
# :memstore_flushsize => 134217728,
|
174
|
-
# :deferred_log_flush => false}
|
175
|
-
|
176
|
-
# Properties of the column families
|
177
|
-
table.families
|
178
|
-
# {"cf"=>
|
179
|
-
# {:blockcache => true,
|
180
|
-
# :blocksize => 65536,
|
181
|
-
# :bloomfilter => "NONE",
|
182
|
-
# :cache_blooms_on_write => false,
|
183
|
-
# :cache_data_on_write => false,
|
184
|
-
# :cache_index_on_write => false,
|
185
|
-
# :compression => "NONE",
|
186
|
-
# :compression_compact => "NONE",
|
187
|
-
# :data_block_encoding => "NONE",
|
188
|
-
# :evict_blocks_on_close => false,
|
189
|
-
# :in_memory => false,
|
190
|
-
# :keep_deleted_cells => false,
|
191
|
-
# :min_versions => 0,
|
192
|
-
# :replication_scope => 0,
|
193
|
-
# :ttl => 2147483647,
|
194
|
-
# :versions => 3}}
|
195
|
-
```
|
196
|
-
|
197
|
-
There are also `raw_` variants of `properties` and `families`.
|
198
|
-
They return properties in their internal String format (mainly used in HBase shell).
|
199
|
-
(See [HTableDescriptor.values](http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HTableDescriptor.html#values) and
|
200
|
-
[HColumnDescriptor.values](http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HColumnDescriptor.html#values))
|
201
|
-
|
202
|
-
```ruby
|
203
|
-
table.raw_properties
|
204
|
-
# {"IS_ROOT" => "false",
|
205
|
-
# "IS_META" => "false",
|
206
|
-
# "MAX_FILESIZE" => "2147483648"}
|
207
|
-
|
208
|
-
table.raw_families
|
209
|
-
# {"cf" =>
|
210
|
-
# {"DATA_BLOCK_ENCODING" => "NONE",
|
211
|
-
# "BLOOMFILTER" => "NONE",
|
212
|
-
# "REPLICATION_SCOPE" => "0",
|
213
|
-
# "VERSIONS" => "3",
|
214
|
-
# "COMPRESSION" => "NONE",
|
215
|
-
# "MIN_VERSIONS" => "0",
|
216
|
-
# "TTL" => "2147483647",
|
217
|
-
# "KEEP_DELETED_CELLS" => "false",
|
218
|
-
# "BLOCKSIZE" => "65536",
|
219
|
-
# "IN_MEMORY" => "false",
|
220
|
-
# "ENCODE_ON_DISK" => "true",
|
221
|
-
# "BLOCKCACHE" => "true"}}
|
222
|
-
```
|
223
|
-
|
224
|
-
These String key-value pairs are not really a part of the public API of HBase, and thus might change over time.
|
225
|
-
However, they are most useful when you need to create a table with the same properties as the existing one.
|
226
|
-
|
227
|
-
```ruby
|
228
|
-
hbase[:dupe_table].create!(table.raw_families, table.raw_properties)
|
229
|
-
```
|
230
|
-
|
231
|
-
With `regions` method, you can even presplit the new table just like the old one.
|
232
|
-
|
233
|
-
```ruby
|
234
|
-
hbase[:dupe_table].create!(
|
235
|
-
table.raw_families,
|
236
|
-
table.raw_properties.merge(
|
237
|
-
:splits => table.regions.map { |r| r[:start_key] }.compact))
|
238
|
-
```
|
239
|
-
|
240
161
|
## Basic operations
|
241
162
|
|
242
163
|
### PUT
|
@@ -329,13 +250,16 @@ row.each do |cell|
|
|
329
250
|
timestamp = cell.timestamp
|
330
251
|
|
331
252
|
# Cell value as Java byte array
|
332
|
-
bytes = cell.
|
253
|
+
bytes = cell.raw
|
333
254
|
|
334
255
|
# Typed access
|
335
256
|
# value_as_string = cell.string
|
336
257
|
# value_as_fixnum = cell.fixnum
|
337
258
|
# ...
|
338
259
|
end
|
260
|
+
|
261
|
+
# Array of HBase::Cells
|
262
|
+
cells = row.to_a
|
339
263
|
```
|
340
264
|
|
341
265
|
#### `to_hash`
|
@@ -697,130 +621,88 @@ For other data types, you can pass your own ColumnInterpreter.
|
|
697
621
|
table.project('cf1:b').aggregate(:sum, MyColumnInterpreter.new)
|
698
622
|
```
|
699
623
|
|
700
|
-
##
|
701
|
-
|
702
|
-
### Lexicographic scan order
|
703
|
-
|
704
|
-
HBase stores rows in the lexicographic order of the rowkeys in their byte array representations.
|
705
|
-
Thus the type of row key affects the scan order.
|
706
|
-
|
707
|
-
```ruby
|
708
|
-
(1..15).times do |i|
|
709
|
-
table.put i, data
|
710
|
-
table.put i.to_s, data
|
711
|
-
end
|
712
|
-
|
713
|
-
table.range(1..3).map { |r| r.rowkey :fixnum }
|
714
|
-
# [1, 2, 3]
|
715
|
-
table.range('1'..'3').map { |r| r.rowkey :string }
|
716
|
-
# %w[1 10 11 12 13 14 15 2 3]
|
717
|
-
```
|
718
|
-
|
719
|
-
### Non-string column qualifier
|
720
|
-
|
721
|
-
If a column qualifier is not a String, *an HBase::ColumnKey instance* should be used
|
722
|
-
instead of a conventional `FAMILY:QUALIFIER` String.
|
723
|
-
|
724
|
-
```ruby
|
725
|
-
table.put 'rowkey',
|
726
|
-
'cf1:col1' => 'Hello world',
|
727
|
-
HBase::ColumnKey(:cf1, 100) => "Byte representation of an 8-byte integer",
|
728
|
-
HBase::ColumnKey(:cf1, bytes) => "Qualifier is an arbitrary byte array"
|
729
|
-
|
730
|
-
table.get('rowkey').string('cf1:col1')
|
731
|
-
table.get('rowkey').string(HBase::ColumnKey(:cf1, 100))
|
732
|
-
# ...
|
733
|
-
```
|
734
|
-
|
735
|
-
### Shorter integers
|
736
|
-
|
737
|
-
A Ruby Fixnum is an 8-byte integer, which is equivalent `long` type in Java.
|
738
|
-
When you want to use shorter integer types such as int, short, or byte,
|
739
|
-
you can then use the special Hash representation of integers.
|
740
|
-
|
741
|
-
```ruby
|
742
|
-
# 4-byte int value as the rowkey
|
743
|
-
table.put({ int: 12345 }, 'cf1:a' => { byte: 100 }, # 1-byte integer
|
744
|
-
'cf1:b' => { short: 200 }, # 2-byte integer
|
745
|
-
'cf1:c' => { int: 300 }, # 4-byte integer
|
746
|
-
'cf1:4' => 400) # Ordinary 8-byte integer
|
747
|
-
|
748
|
-
result = table.get(int: 12345)
|
749
|
-
|
750
|
-
result.byte('cf1:a') # 100
|
751
|
-
result.short('cf1:b') # 200
|
752
|
-
result.int('cf1:c') # 300
|
753
|
-
# ...
|
754
|
-
```
|
755
|
-
|
756
|
-
### Working with byte arrays
|
757
|
-
|
758
|
-
In HBase, virtually everything is stored as a byte array.
|
759
|
-
Although *hbase-jruby* tries hard to hide the fact,
|
760
|
-
at some point you may need to get your hands dirty with native Java byte arrays.
|
761
|
-
For example, it's [a common practice] [1] to use a composite row key,
|
762
|
-
which is a concatenation of several components of different types.
|
763
|
-
|
764
|
-
[1]: http://blog.sematext.com/2012/08/09/consider-using-fuzzyrowfilter-when-in-need-for-secondary-indexes-in-hbase/
|
765
|
-
|
766
|
-
`HBase::ByteArray` is a boxed class for native Java byte arrays,
|
767
|
-
which makes byte array manipulation much easier.
|
768
|
-
|
769
|
-
A ByteArray can be created as a concatenation of any number of objects.
|
770
|
-
|
771
|
-
```ruby
|
772
|
-
ba = HBase::ByteArray(100, 3.14, {int: 300}, "Hello World")
|
773
|
-
```
|
774
|
-
|
775
|
-
Then you can slice it and decode each part,
|
624
|
+
## Table inspection
|
776
625
|
|
777
626
|
```ruby
|
778
|
-
#
|
779
|
-
|
780
|
-
|
627
|
+
# Table properties
|
628
|
+
table.properties
|
629
|
+
# {:max_filesize => 2147483648,
|
630
|
+
# :readonly => false,
|
631
|
+
# :memstore_flushsize => 134217728,
|
632
|
+
# :deferred_log_flush => false}
|
781
633
|
|
782
|
-
|
783
|
-
|
634
|
+
# Properties of the column families
|
635
|
+
table.families
|
636
|
+
# {"cf"=>
|
637
|
+
# {:blockcache => true,
|
638
|
+
# :blocksize => 65536,
|
639
|
+
# :bloomfilter => "NONE",
|
640
|
+
# :cache_blooms_on_write => false,
|
641
|
+
# :cache_data_on_write => false,
|
642
|
+
# :cache_index_on_write => false,
|
643
|
+
# :compression => "NONE",
|
644
|
+
# :compression_compact => "NONE",
|
645
|
+
# :data_block_encoding => "NONE",
|
646
|
+
# :evict_blocks_on_close => false,
|
647
|
+
# :in_memory => false,
|
648
|
+
# :keep_deleted_cells => false,
|
649
|
+
# :min_versions => 0,
|
650
|
+
# :replication_scope => 0,
|
651
|
+
# :ttl => 2147483647,
|
652
|
+
# :versions => 3}}
|
784
653
|
```
|
785
654
|
|
786
|
-
|
655
|
+
There are also `raw_` variants of `properties` and `families`.
|
656
|
+
They return properties in their internal String format (mainly used in HBase shell).
|
657
|
+
(See [HTableDescriptor.values](http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HTableDescriptor.html#values) and
|
658
|
+
[HColumnDescriptor.values](http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HColumnDescriptor.html#values))
|
787
659
|
|
788
660
|
```ruby
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
concatenate another ByteArray,
|
661
|
+
table.raw_properties
|
662
|
+
# {"IS_ROOT" => "false",
|
663
|
+
# "IS_META" => "false",
|
664
|
+
# "MAX_FILESIZE" => "2147483648"}
|
794
665
|
|
795
|
-
|
796
|
-
|
666
|
+
table.raw_families
|
667
|
+
# {"cf" =>
|
668
|
+
# {"DATA_BLOCK_ENCODING" => "NONE",
|
669
|
+
# "BLOOMFILTER" => "NONE",
|
670
|
+
# "REPLICATION_SCOPE" => "0",
|
671
|
+
# "VERSIONS" => "3",
|
672
|
+
# "COMPRESSION" => "NONE",
|
673
|
+
# "MIN_VERSIONS" => "0",
|
674
|
+
# "TTL" => "2147483647",
|
675
|
+
# "KEEP_DELETED_CELLS" => "false",
|
676
|
+
# "BLOCKSIZE" => "65536",
|
677
|
+
# "IN_MEMORY" => "false",
|
678
|
+
# "ENCODE_ON_DISK" => "true",
|
679
|
+
# "BLOCKCACHE" => "true"}}
|
797
680
|
```
|
798
681
|
|
799
|
-
|
682
|
+
These String key-value pairs are not really a part of the public API of HBase, and thus might change over time.
|
683
|
+
However, they are most useful when you need to create a table with the same properties as the existing one.
|
800
684
|
|
801
685
|
```ruby
|
802
|
-
|
803
|
-
ba.shift(:boolean)
|
804
|
-
ba.shift(:fixnum)
|
805
|
-
ba.shift(:float)
|
806
|
-
ba.shift(:int)
|
807
|
-
ba.shift(:string, 11) # Byte length must be given as Strings are not fixed in size
|
686
|
+
hbase[:dupe_table].create!(table.raw_families, table.raw_properties)
|
808
687
|
```
|
809
688
|
|
810
|
-
`
|
689
|
+
With `regions` method, you can even presplit the new table just like the old one.
|
811
690
|
|
812
691
|
```ruby
|
813
|
-
|
692
|
+
hbase[:dupe_table].create!(
|
693
|
+
table.raw_families,
|
694
|
+
table.raw_properties.merge(
|
695
|
+
:splits => table.regions.map { |r| r[:start_key] }.compact))
|
814
696
|
```
|
815
697
|
|
816
|
-
|
698
|
+
## Table administration
|
817
699
|
|
818
700
|
`HBase#Table` provides a number of *bang_methods!* for table administration tasks.
|
819
701
|
They run synchronously, except when mentioned otherwise (e.g. `HTable#split!`).
|
820
702
|
Some of them take an optional block to allow progress monitoring
|
821
703
|
and come with non-bang, asynchronous counterparts.
|
822
704
|
|
823
|
-
|
705
|
+
### Creation and alteration
|
824
706
|
|
825
707
|
```ruby
|
826
708
|
# Create a table with configurable table-level properties
|
@@ -856,7 +738,7 @@ table.alter(
|
|
856
738
|
)
|
857
739
|
```
|
858
740
|
|
859
|
-
|
741
|
+
#### List of column family properties
|
860
742
|
|
861
743
|
http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HColumnDescriptor.html
|
862
744
|
|
@@ -882,7 +764,7 @@ Some of the properties are only available on recent versions of HBase.
|
|
882
764
|
| `:ttl` | Fixnum | Time-to-live of cell contents, in seconds |
|
883
765
|
| `:versions` | Fixnum | The maximum number of versions. (By default, all available versions are retrieved.) |
|
884
766
|
|
885
|
-
|
767
|
+
#### List of table properties
|
886
768
|
|
887
769
|
http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HTableDescriptor.html
|
888
770
|
|
@@ -894,7 +776,7 @@ http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/HTableDescriptor.html
|
|
894
776
|
| `:deferred_log_flush` | Boolean | Defer the log edits syncing to the file system |
|
895
777
|
| `:splits` | Array | Region split points |
|
896
778
|
|
897
|
-
|
779
|
+
### Managing column families
|
898
780
|
|
899
781
|
```ruby
|
900
782
|
# Add column family
|
@@ -908,7 +790,7 @@ table.alter_family! :cf2, :bloomfilter => :rowcol
|
|
908
790
|
table.delete_family! :cf1
|
909
791
|
```
|
910
792
|
|
911
|
-
|
793
|
+
### Coprocessors
|
912
794
|
|
913
795
|
```ruby
|
914
796
|
# Add Coprocessor
|
@@ -922,31 +804,165 @@ table.add_coprocessor! cp_class_name2,
|
|
922
804
|
table.remove_coprocessor! cp_class_name1
|
923
805
|
```
|
924
806
|
|
925
|
-
|
807
|
+
### Region splits (asynchronous)
|
926
808
|
|
927
809
|
```ruby
|
928
810
|
table.split!(1000)
|
929
811
|
table.split!(2000, 3000)
|
930
812
|
```
|
931
813
|
|
932
|
-
|
814
|
+
### Snapshots
|
815
|
+
|
816
|
+
```ruby
|
817
|
+
# Returns a list of all snapshot information
|
818
|
+
hbase.snapshots
|
819
|
+
|
820
|
+
# Table snapshots
|
821
|
+
table.snapshots
|
822
|
+
# Equivalent to
|
823
|
+
# hbase.snapshots.select { |info| info[:table] == table.name }
|
824
|
+
|
825
|
+
# Creating a snapshot
|
826
|
+
table.snapshot! 'my_table_snapshot'
|
827
|
+
```
|
828
|
+
|
829
|
+
### Advanced table administration
|
933
830
|
|
934
831
|
You can perform other types of administrative tasks
|
935
|
-
with native Java [HBaseAdmin object](http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/HBaseAdmin.html),
|
832
|
+
with the native Java [HBaseAdmin object](http://hbase.apache.org/apidocs/org/apache/hadoop/hbase/client/HBaseAdmin.html),
|
936
833
|
which can be obtained by `HBase#admin` method. Optionally, a block can be given
|
937
|
-
so that the
|
834
|
+
so that the object is automatically closed at the end of the given block.
|
938
835
|
|
939
836
|
```ruby
|
940
837
|
admin = hbase.admin
|
941
838
|
# ...
|
942
839
|
admin.close
|
943
840
|
|
944
|
-
#
|
841
|
+
# Access native HBaseAdmin object within the block
|
945
842
|
hbase.admin do |admin|
|
843
|
+
admin.snapshot 'my_snapshot', 'my_table'
|
844
|
+
admin.cloneSnapshot 'my_snapshot', 'my_clone_table'
|
845
|
+
admin.deleteSnapshot 'my_snapshot'
|
946
846
|
# ...
|
947
847
|
end
|
948
848
|
```
|
949
849
|
|
850
|
+
## Advanced topics
|
851
|
+
|
852
|
+
### Lexicographic scan order
|
853
|
+
|
854
|
+
HBase stores rows in the lexicographic order of the rowkeys in their byte array representations.
|
855
|
+
Thus the type of row key affects the scan order.
|
856
|
+
|
857
|
+
```ruby
|
858
|
+
(1..15).times do |i|
|
859
|
+
table.put i, data
|
860
|
+
table.put i.to_s, data
|
861
|
+
end
|
862
|
+
|
863
|
+
table.range(1..3).map { |r| r.rowkey :fixnum }
|
864
|
+
# [1, 2, 3]
|
865
|
+
table.range('1'..'3').map { |r| r.rowkey :string }
|
866
|
+
# %w[1 10 11 12 13 14 15 2 3]
|
867
|
+
```
|
868
|
+
|
869
|
+
### Non-string column qualifier
|
870
|
+
|
871
|
+
If a column qualifier is not a String, *an HBase::ColumnKey instance* should be used
|
872
|
+
instead of a conventional `FAMILY:QUALIFIER` String.
|
873
|
+
|
874
|
+
```ruby
|
875
|
+
table.put 'rowkey',
|
876
|
+
'cf1:col1' => 'Hello world',
|
877
|
+
HBase::ColumnKey(:cf1, 100) => "Byte representation of an 8-byte integer",
|
878
|
+
HBase::ColumnKey(:cf1, bytes) => "Qualifier is an arbitrary byte array"
|
879
|
+
|
880
|
+
table.get('rowkey').string('cf1:col1')
|
881
|
+
table.get('rowkey').string(HBase::ColumnKey(:cf1, 100))
|
882
|
+
# ...
|
883
|
+
```
|
884
|
+
|
885
|
+
### Shorter integers
|
886
|
+
|
887
|
+
A Ruby Fixnum is an 8-byte integer, which is equivalent `long` type in Java.
|
888
|
+
When you want to use shorter integer types such as int, short, or byte,
|
889
|
+
you can then use the special Hash representation of integers.
|
890
|
+
|
891
|
+
```ruby
|
892
|
+
# 4-byte int value as the rowkey
|
893
|
+
table.put({ int: 12345 }, 'cf1:a' => { byte: 100 }, # 1-byte integer
|
894
|
+
'cf1:b' => { short: 200 }, # 2-byte integer
|
895
|
+
'cf1:c' => { int: 300 }, # 4-byte integer
|
896
|
+
'cf1:4' => 400) # Ordinary 8-byte integer
|
897
|
+
|
898
|
+
result = table.get(int: 12345)
|
899
|
+
|
900
|
+
result.byte('cf1:a') # 100
|
901
|
+
result.short('cf1:b') # 200
|
902
|
+
result.int('cf1:c') # 300
|
903
|
+
# ...
|
904
|
+
```
|
905
|
+
|
906
|
+
### Working with byte arrays
|
907
|
+
|
908
|
+
In HBase, virtually everything is stored as a byte array.
|
909
|
+
Although *hbase-jruby* tries hard to hide the fact,
|
910
|
+
at some point you may need to get your hands dirty with native Java byte arrays.
|
911
|
+
For example, it's [a common practice] [1] to use a composite row key,
|
912
|
+
which is a concatenation of several components of different types.
|
913
|
+
|
914
|
+
[1]: http://blog.sematext.com/2012/08/09/consider-using-fuzzyrowfilter-when-in-need-for-secondary-indexes-in-hbase/
|
915
|
+
|
916
|
+
`HBase::ByteArray` is a boxed class for native Java byte arrays,
|
917
|
+
which makes byte array manipulation much easier.
|
918
|
+
|
919
|
+
A ByteArray can be created as a concatenation of any number of objects.
|
920
|
+
|
921
|
+
```ruby
|
922
|
+
ba = HBase::ByteArray(100, 3.14, {int: 300}, "Hello World")
|
923
|
+
```
|
924
|
+
|
925
|
+
Then you can slice it and decode each part,
|
926
|
+
|
927
|
+
```ruby
|
928
|
+
# Slicing
|
929
|
+
first = ba[0, 8]
|
930
|
+
second = ba[8...16]
|
931
|
+
|
932
|
+
first.decode(:fixnum) # 100
|
933
|
+
second.decode(:float) # 3.14
|
934
|
+
```
|
935
|
+
|
936
|
+
append, prepend more elements to it,
|
937
|
+
|
938
|
+
```ruby
|
939
|
+
ba.unshift 200, true
|
940
|
+
ba << { short: 300 }
|
941
|
+
```
|
942
|
+
|
943
|
+
concatenate another ByteArray,
|
944
|
+
|
945
|
+
```ruby
|
946
|
+
ba += HBase::ByteArray(1024)
|
947
|
+
```
|
948
|
+
|
949
|
+
or shift decoded objects from it.
|
950
|
+
|
951
|
+
```ruby
|
952
|
+
ba.shift(:fixnum)
|
953
|
+
ba.shift(:boolean)
|
954
|
+
ba.shift(:fixnum)
|
955
|
+
ba.shift(:float)
|
956
|
+
ba.shift(:int)
|
957
|
+
ba.shift(:string, 11) # Byte length must be given as Strings are not fixed in size
|
958
|
+
```
|
959
|
+
|
960
|
+
`ByteArray#java` method returns the underlying native Java byte array.
|
961
|
+
|
962
|
+
```ruby
|
963
|
+
ba.java # Returns the native Java byte array (byte[])
|
964
|
+
```
|
965
|
+
|
950
966
|
## Test
|
951
967
|
|
952
968
|
```bash
|
data/lib/hbase-jruby/cell.rb
CHANGED
@@ -70,13 +70,31 @@ class Cell
|
|
70
70
|
end
|
71
71
|
alias sym symbol
|
72
72
|
|
73
|
-
# Returns the column value as a Fixnum
|
73
|
+
# Returns the 8-byte column value as a Fixnum
|
74
74
|
# @return [Fixnum]
|
75
75
|
def fixnum
|
76
76
|
Util.from_bytes :fixnum, value
|
77
77
|
end
|
78
78
|
alias long fixnum
|
79
79
|
|
80
|
+
# Returns the 4-byte column value as a Fixnum
|
81
|
+
# @return [Fixnum]
|
82
|
+
def int
|
83
|
+
Util.from_bytes :int, value
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns the 2-byte column value as a Fixnum
|
87
|
+
# @return [Fixnum]
|
88
|
+
def short
|
89
|
+
Util.from_bytes :short, value
|
90
|
+
end
|
91
|
+
|
92
|
+
# Returns the 1-byte column value as a Fixnum
|
93
|
+
# @return [Fixnum]
|
94
|
+
def byte
|
95
|
+
Util.from_bytes :byte, value
|
96
|
+
end
|
97
|
+
|
80
98
|
# Returns the column value as a BigDecimal
|
81
99
|
# @return [BigDecimal]
|
82
100
|
def bigdecimal
|
@@ -12,8 +12,8 @@ class HBase
|
|
12
12
|
# https://ccp.cloudera.com/display/SUPPORT/CDH+Downloads
|
13
13
|
SUPPORTED_PROFILES = {
|
14
14
|
# Prefix => Latest known version
|
15
|
-
'cdh4.2' => 'cdh4.2.
|
16
|
-
'cdh4.1' => 'cdh4.1.
|
15
|
+
'cdh4.2' => 'cdh4.2.1',
|
16
|
+
'cdh4.1' => 'cdh4.1.4',
|
17
17
|
'cdh3' => 'cdh3u6',
|
18
18
|
'0.95' => '0.95.0',
|
19
19
|
'0.94' => '0.94.6.1',
|
data/lib/hbase-jruby/hbase.rb
CHANGED
@@ -127,6 +127,17 @@ class HBase
|
|
127
127
|
end
|
128
128
|
alias [] table
|
129
129
|
|
130
|
+
# Returns an Array of snapshot information
|
131
|
+
# @return [Array<Hash>]
|
132
|
+
def snapshots
|
133
|
+
with_admin { |admin| admin.listSnapshots }.map { |sd|
|
134
|
+
props = sd.getAllFields.map { |k, v|
|
135
|
+
[k.name.to_sym, v.respond_to?(:name) ? v.name : v]
|
136
|
+
}
|
137
|
+
Hash[props]
|
138
|
+
}
|
139
|
+
end
|
140
|
+
|
130
141
|
private
|
131
142
|
def check_closed
|
132
143
|
raise RuntimeError, "Connection already closed" if closed?
|
@@ -3,7 +3,7 @@ require 'bigdecimal'
|
|
3
3
|
class HBase
|
4
4
|
# Represents a row returned by HBase
|
5
5
|
# @author Junegunn Choi <junegunn.c@gmail.com>
|
6
|
-
class
|
6
|
+
class Row
|
7
7
|
include Enumerable
|
8
8
|
|
9
9
|
# Returns the rowkey of the row
|
@@ -450,6 +450,9 @@ private
|
|
450
450
|
end
|
451
451
|
}
|
452
452
|
end
|
453
|
-
end#
|
453
|
+
end#Row
|
454
454
|
end#HBase
|
455
455
|
|
456
|
+
# For backward compatibility
|
457
|
+
HBase::Result = HBase::Row
|
458
|
+
|
data/lib/hbase-jruby/scoped.rb
CHANGED
@@ -24,7 +24,7 @@ class Scoped
|
|
24
24
|
if block_given?
|
25
25
|
scanner = htable.getScanner(filtered_scan)
|
26
26
|
scanner.each do |result|
|
27
|
-
cnt += 1 if yield(
|
27
|
+
cnt += 1 if yield(Row.send(:new, result))
|
28
28
|
end
|
29
29
|
else
|
30
30
|
scanner = htable.getScanner(filtered_scan_minimum)
|
@@ -41,29 +41,29 @@ class Scoped
|
|
41
41
|
# Single GET.
|
42
42
|
# Gets a record with the given rowkey. If the record is not found, nil is returned.
|
43
43
|
# @param [Object] rowkey Rowkey
|
44
|
-
# @return [HBase::
|
44
|
+
# @return [HBase::Row, nil]
|
45
45
|
# @overload get(rowkeys)
|
46
46
|
# Batch GET. Gets an array of records with the given rowkeys.
|
47
47
|
# Nonexistent records will be returned as nils.
|
48
48
|
# @param [Array<Object>] *rowkeys Rowkeys
|
49
|
-
# @return [Array<HBase::
|
49
|
+
# @return [Array<HBase::Row>]
|
50
50
|
def get rowkeys
|
51
51
|
check_closed
|
52
52
|
|
53
53
|
case rowkeys
|
54
54
|
when Array
|
55
55
|
htable.get(rowkeys.map { |rk| getify rk }).map { |result|
|
56
|
-
result.isEmpty ? nil :
|
56
|
+
result.isEmpty ? nil : Row.new(result)
|
57
57
|
}
|
58
58
|
else
|
59
59
|
result = htable.get(getify rowkeys)
|
60
|
-
result.isEmpty ? nil :
|
60
|
+
result.isEmpty ? nil : Row.new(result)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
64
|
# Iterate through the scope.
|
65
65
|
# @yield [row] Yields each row in the scope
|
66
|
-
# @yieldparam [HBase::
|
66
|
+
# @yieldparam [HBase::Row] row
|
67
67
|
def each
|
68
68
|
check_closed
|
69
69
|
|
@@ -71,7 +71,7 @@ class Scoped
|
|
71
71
|
begin
|
72
72
|
scanner = htable.getScanner(filtered_scan)
|
73
73
|
scanner.each do |result|
|
74
|
-
yield
|
74
|
+
yield Row.send(:new, result)
|
75
75
|
end
|
76
76
|
ensure
|
77
77
|
scanner.close if scanner
|
@@ -240,6 +240,21 @@ class Table
|
|
240
240
|
end
|
241
241
|
end
|
242
242
|
|
243
|
+
# Creates a snapshot of the table
|
244
|
+
# @param [String] snapshot_name Snapshot name
|
245
|
+
# @return [nil]
|
246
|
+
def snapshot! snapshot_name
|
247
|
+
with_admin do |admin|
|
248
|
+
admin.snapshot snapshot_name, @name
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
# Returns an Array of snapshot information for this table
|
253
|
+
# @return [Array<Hash>]
|
254
|
+
def snapshots
|
255
|
+
@hbase.snapshots.select { |h| h[:table] == @name }
|
256
|
+
end
|
257
|
+
|
243
258
|
private
|
244
259
|
COLUMN_PROPERTIES = {
|
245
260
|
:blockcache => { :set => :setBlockCacheEnabled, :get => :isBlockCacheEnabled },
|
data/lib/hbase-jruby/table.rb
CHANGED
data/lib/hbase-jruby/version.rb
CHANGED
data/lib/hbase-jruby.rb
CHANGED
@@ -14,7 +14,7 @@ require "hbase-jruby/scoped"
|
|
14
14
|
require "hbase-jruby/table"
|
15
15
|
require "hbase-jruby/table/admin"
|
16
16
|
require "hbase-jruby/table/inspection"
|
17
|
-
require "hbase-jruby/
|
17
|
+
require "hbase-jruby/row"
|
18
18
|
require 'hbase-jruby/hbase'
|
19
19
|
|
20
20
|
HBase.import_java_classes!
|
data/test/test_cell.rb
CHANGED
@@ -11,13 +11,16 @@ class TestCell < Test::Unit::TestCase
|
|
11
11
|
def test_cell
|
12
12
|
ts = Time.now.to_i * 1000
|
13
13
|
{
|
14
|
-
'value'
|
15
|
-
:value
|
16
|
-
123
|
17
|
-
123.456
|
18
|
-
true
|
19
|
-
false
|
20
|
-
BigDecimal.new("123.456")
|
14
|
+
'value' => :string,
|
15
|
+
:value => :symbol,
|
16
|
+
123 => :fixnum,
|
17
|
+
123.456 => :float,
|
18
|
+
true => :boolean,
|
19
|
+
false => :boolean,
|
20
|
+
BigDecimal.new("123.456") => :bigdecimal,
|
21
|
+
{ :int => 10240 } => :int,
|
22
|
+
{ :short => 1024 } => :short,
|
23
|
+
{ :byte => 100 } => :byte
|
21
24
|
}.each do |value, type|
|
22
25
|
kv = KeyValue.new("rowkey".to_java_bytes, "hello".to_java_bytes, "world".to_java_bytes, ts, Util.to_bytes(value))
|
23
26
|
cell = HBase::Cell.new(kv)
|
@@ -26,7 +29,12 @@ class TestCell < Test::Unit::TestCase
|
|
26
29
|
assert_equal "hello", cell.cf, cell.family
|
27
30
|
assert_equal "world", cell.cq, cell.qualifier
|
28
31
|
assert_equal ts, cell.ts
|
29
|
-
|
32
|
+
if value.is_a?(Hash)
|
33
|
+
assert_equal value.values.first, cell.send(type)
|
34
|
+
else
|
35
|
+
assert_equal value, cell.send(type)
|
36
|
+
end
|
37
|
+
assert HBase::Util.java_bytes?(cell.raw)
|
30
38
|
assert_equal HBase::ColumnKey.new(:hello, :world), cell.column_key
|
31
39
|
assert_instance_of String, cell.inspect
|
32
40
|
end
|
data/test/test_table_admin.rb
CHANGED
@@ -259,5 +259,37 @@ class TestTableAdmin < TestHBaseJRubyBase
|
|
259
259
|
@table.drop!
|
260
260
|
end
|
261
261
|
end
|
262
|
+
|
263
|
+
def test_snapshots
|
264
|
+
@hbase.admin do |admin|
|
265
|
+
@hbase.snapshots.map { |e| e[:name] }.each do |name|
|
266
|
+
admin.deleteSnapshot name
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
assert_equal 0, @hbase.snapshots.length
|
271
|
+
assert_equal 0, @table.snapshots.length
|
272
|
+
|
273
|
+
@table.snapshot! 'hbase_jruby_test_snapshot1'
|
274
|
+
@table.snapshot! 'hbase_jruby_test_snapshot2'
|
275
|
+
|
276
|
+
assert_equal 2, @hbase.snapshots.length
|
277
|
+
assert_equal 2, @table.snapshots.length # FIXME: table-wise snapshots
|
278
|
+
|
279
|
+
@hbase.snapshots.each do |snapshot|
|
280
|
+
assert_equal @table.name, snapshot[:table]
|
281
|
+
assert_match /hbase_jruby_test_snapshot[12]/, snapshot[:name]
|
282
|
+
end
|
283
|
+
|
284
|
+
@hbase.admin do |admin|
|
285
|
+
admin.deleteSnapshot 'hbase_jruby_test_snapshot1'
|
286
|
+
admin.deleteSnapshot 'hbase_jruby_test_snapshot2'
|
287
|
+
end
|
288
|
+
|
289
|
+
assert_equal 0, @hbase.snapshots.length
|
290
|
+
assert_equal 0, @table.snapshots.length
|
291
|
+
rescue Exception
|
292
|
+
# TODO: Only works on HBase 0.94 or above
|
293
|
+
end
|
262
294
|
end unless ENV['HBASE_JRUBY_TEST_SKIP_ADMIN']
|
263
295
|
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: hbase-jruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.2.
|
5
|
+
version: 0.2.5
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Junegunn Choi
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: test-unit
|
@@ -69,7 +69,7 @@ files:
|
|
69
69
|
- lib/hbase-jruby/dependency.rb
|
70
70
|
- lib/hbase-jruby/hbase.rb
|
71
71
|
- lib/hbase-jruby/pom/pom.xml.erb
|
72
|
-
- lib/hbase-jruby/
|
72
|
+
- lib/hbase-jruby/row.rb
|
73
73
|
- lib/hbase-jruby/scoped.rb
|
74
74
|
- lib/hbase-jruby/scoped/aggregation.rb
|
75
75
|
- lib/hbase-jruby/table.rb
|