| #!/usr/bin/perl |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| # |
| |
| use strict; |
| use warnings; |
| |
| # Change the path here to point to your thrift directory. |
| use lib '/Users/sergey/Downloads/thrift/lib/perl/lib'; |
| use lib 'gen-perl'; |
| |
| use Thrift::Socket; |
| use Thrift::BufferedTransport; |
| use Thrift::BinaryProtocol; |
| use Hbase::Hbase; |
| use Data::Dumper; |
| |
| sub printRow($) |
| { |
| my $rowresult = shift; |
| |
| return if (!$rowresult || @{$rowresult} < 1); |
| # rowresult is presummed to be a Hbase::TRowResult object |
| |
| printf ("row: {%s}, cols: \n", $rowresult->[0]->{row}); |
| my $values = $rowresult->[0]->{columns}; |
| foreach my $key ( sort ( keys %{$values} ) ) |
| { |
| printf ("{%s} => {%s}\n", $key, $values->{$key}->{value}); |
| } |
| } |
| |
| my $host = $ARGV[0] || "localhost"; |
| my $port = $ARGV[1] || 9090; |
| |
| my $socket = Thrift::Socket->new ($host, $port); |
| $socket->setSendTimeout (10000); # Ten seconds (value is in millisec) |
| $socket->setRecvTimeout (20000); # Twenty seconds (value is in millisec) |
| |
| my $transport = Thrift::BufferedTransport->new ($socket); |
| my $protocol = Thrift::BinaryProtocol->new ($transport); |
| my $client = Hbase::HbaseClient->new ($protocol); |
| |
| eval { |
| $transport->open (); |
| }; |
| if ($@) |
| { |
| print "Unable to connect: $@->{message}\n"; |
| exit 1; |
| } |
| |
| my $demo_table = "demo_table"; |
| |
| print "scanning tables...\n"; |
| |
| # |
| # Search for all the tables in the HBase DB, return value is an arrayref |
| # |
| my $tables = $client->getTableNames(); |
| foreach my $table (sort @{$tables}) |
| { |
| print " found {$table}\n"; |
| # This client will re-create the $demo_table, so we need to drop it first |
| if ($table eq $demo_table) |
| { |
| # Before we can drop a table, it has to be disabled first |
| if ($client->isTableEnabled ($table)) |
| { |
| print " disabling table: {$table}\n"; |
| $client->disableTable ($table); |
| } |
| # We assume the table has been disabled at this point |
| print " deleting table: {$table}\n"; |
| $client->deleteTable ($table); |
| } |
| } |
| |
| # |
| # Create the demo table with two column families, entry: and unused: |
| # |
| my $columns = [ |
| Hbase::ColumnDescriptor->new ( { name => "entry:", maxVersions => 10 } ), |
| Hbase::ColumnDescriptor->new ( { name => "unused:" } ), |
| ]; |
| |
| print "creating table: {$demo_table}\n"; |
| eval { |
| # This can throw Hbase::IllegalArgument (HASH) |
| $client->createTable ( $demo_table, $columns ); |
| }; |
| if ($@) |
| { |
| die "ERROR: Unable to create table {$demo_table}: $@->{message}\n"; |
| } |
| |
| print "column families in {$demo_table}:\n"; |
| my $descriptors = $client->getColumnDescriptors ($demo_table); |
| foreach my $col (sort keys %{$descriptors}) |
| { |
| printf (" column: {%s}, maxVer: {%s}\n", $descriptors->{$col}->{name}, $descriptors->{$col}->{maxVersions} ); |
| } |
| |
| my %dummy_attributes = (); |
| |
| # |
| # Test UTF-8 handling |
| # |
| my $invalid = "foo-\xfc\xa1\xa1\xa1\xa1\xa1"; |
| my $valid = "foo-\xE7\x94\x9F\xE3\x83\x93\xE3\x83\xBC\xE3\x83\xAB"; |
| |
| # non-utf8 is fine for data |
| my $key = "foo"; |
| my $mutations = [ Hbase::Mutation->new ( { column => "entry:$key", value => $invalid } ) ]; |
| $client->mutateRow ( $demo_table, $key, $mutations, %dummy_attributes ); |
| |
| # try emptry strings |
| $key = ""; |
| $mutations = [ Hbase::Mutation->new ( { column => "entry:$key", value => "" } ) ]; |
| $client->mutateRow ( $demo_table, $key, $mutations, %dummy_attributes ); |
| |
| # this row name is valid utf8 |
| $key = "foo"; |
| # This is another way to use the Mutation class |
| my $mutation = Hbase::Mutation->new (); |
| $mutation->{column} = "entry:$key"; |
| $mutation->{value} = $valid; |
| $mutations = [ $mutation ]; |
| $client->mutateRow ( $demo_table, $key, $mutations, %dummy_attributes ); |
| |
| # non-utf8 is not allowed in row names |
| eval { |
| $mutations = [ Hbase::Mutation->new ( { column => "entry:$key", value => $invalid } ) ]; |
| # this can throw a TApplicationException (HASH) error |
| $client->mutateRow ($demo_table, $key, $mutations, %dummy_attributes); |
| die ("shouldn't get here!"); |
| }; |
| if ($@) |
| { |
| print "expected error: $@->{message}\n"; |
| } |
| |
| # |
| # Run a scanner on the rows we just created |
| # |
| print "Starting scanner...\n"; |
| $key = ""; |
| # scannerOpen expects ( table, key, <column descriptors> ) |
| # if key is empty, it searches for all entries in the table |
| # if column descriptors is empty, it searches for all column descriptors within the table |
| my $scanner = $client->scannerOpen ( $demo_table, $key, [ "entry:" ], %dummy_attributes ); |
| eval { |
| |
| # scannerGet returns an empty arrayref (instead of an undef) to indicate no results |
| my $result = $client->scannerGet ( $scanner ); |
| while ( $result && @{$result} > 0 ) |
| { |
| printRow ( $result ); |
| $result = $client->scannerGet ( $scanner ); |
| } |
| |
| $client->scannerClose ( $scanner ); |
| print "Scanner finished\n"; |
| }; |
| if ($@) |
| { |
| $client->scannerClose ( $scanner ); |
| print "Scanner finished\n"; |
| } |
| |
| # |
| # Run some operations on a bunch of rows |
| # |
| for (my $e = 100; $e > 0; $e--) |
| { |
| # format row keys as "00000" to "00100"; |
| my $row = sprintf ("%05d", $e); |
| |
| $mutations = [ Hbase::Mutation->new ( { column => "unused:", value => "DELETE_ME" } ) ]; |
| $client->mutateRow ( $demo_table, $row, $mutations, %dummy_attributes ); |
| printRow ( $client->getRow ( $demo_table, $row ) ); |
| $client->deleteAllRow ( $demo_table, $row ); |
| |
| $mutations = [ |
| Hbase::Mutation->new ( { column => "entry:num", value => "0" } ), |
| Hbase::Mutation->new ( { column => "entry:foo", value => "FOO" } ), |
| ]; |
| $client->mutateRow ( $demo_table, $row, $mutations, %dummy_attributes ); |
| printRow ( $client->getRow ( $demo_table, $row, %dummy_attributes ) ); |
| |
| $mutations = [ |
| Hbase::Mutation->new ( { column => "entry:foo", isDelete => 1 } ), |
| Hbase::Mutation->new ( { column => "entry:num", value => -1 } ), |
| ]; |
| $client->mutateRow ( $demo_table, $row, $mutations, %dummy_attributes ); |
| printRow ( $client->getRow ( $demo_table, $row, %dummy_attributes ) ); |
| |
| $mutations = [ |
| Hbase::Mutation->new ( { column => "entry:num", value => $e } ), |
| Hbase::Mutation->new ( { column => "entry:sqr", value => $e * $e } ), |
| ]; |
| $client->mutateRow ( $demo_table, $row, $mutations, %dummy_attributes ); |
| printRow ( $client->getRow ( $demo_table, $row, %dummy_attributes ) ); |
| |
| $mutations = [ |
| Hbase::Mutation->new ( { column => "entry:num", value => -999 } ), |
| Hbase::Mutation->new ( { column => "entry:sqr", isDelete => 1 } ), |
| ]; |
| |
| # mutateRowTs => modify the row entry at the specified timestamp (ts) |
| $client->mutateRowTs ( $demo_table, $row, $mutations, 1, %dummy_attributes ); # shouldn't override latest |
| printRow ( $client->getRow ( $demo_table, $row, %dummy_attributes ) ); |
| |
| my $versions = $client->getVer ( $demo_table, $row, "entry:num", 10, %dummy_attributes ); |
| printf ( "row: {%s}, values: \n", $row ); |
| foreach my $v ( @{$versions} ) |
| { |
| printf ( " {%s} @ {%s}\n", $v->{value}, $v->{timestamp} ); |
| } |
| |
| eval { |
| |
| my $result = $client->get ( $demo_table, $row, "entry:foo", %dummy_attributes ); |
| |
| # Unfortunately, the API returns an empty arrayref instead of undef |
| # to signify a "not found", which makes it slightly inconvenient. |
| die "shouldn't get here!" if ($result && @{$result} > 0); |
| |
| if (!$result || ($result && @{$result} < 1)) |
| { |
| print "expected: {$row} not found in {$demo_table}\n"; |
| } |
| }; |
| if ($@) |
| { |
| print "expected error: $@\n"; |
| } |
| } |
| |
| my $column_descriptor = $client->getColumnDescriptors ( $demo_table ); |
| $columns = []; |
| foreach my $col ( keys %{$column_descriptor} ) |
| { |
| my $colname = $column_descriptor->{$col}->{name}; |
| print "column with name: {$colname}\n"; |
| push ( @{$columns}, $colname); |
| } |
| |
| print "Starting scanner...\n"; |
| $scanner = $client->scannerOpenWithStop ( $demo_table, "00020", "00040", $columns, %dummy_attributes ); |
| eval { |
| |
| # scannerGet returns an empty arrayref (instead of an undef) to indicate no results |
| my $result = $client->scannerGet ( $scanner ); |
| while ( $result && @$result > 0 ) |
| { |
| printRow ( $result ); |
| $result = $client->scannerGet ( $scanner ); |
| } |
| |
| $client->scannerClose ( $scanner ); |
| print "Scanner finished\n"; |
| }; |
| if ($@) |
| { |
| $client->scannerClose ( $scanner ); |
| print "Scanner finished\n"; |
| } |
| |
| $transport->close (); |
| |
| exit 0; |
| |