hbase-jruby 0.2.4-java → 0.2.5-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|