296 lines
8.8 KiB
Perl
296 lines
8.8 KiB
Perl
#!/usr/bin/perl
|
|
# Copyright 2011 The Apache Software Foundation
|
|
#
|
|
# 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.
|
|
#
|
|
#
|
|
|
|
# Instructions:
|
|
# 1. Run Thrift to generate the perl module HBase
|
|
# thrift --gen perl ../../../src/main/resources/org/apache/hadoop/hbase/thrift/Hbase.thrift
|
|
# 2. Add the gen-perl/Hbase directory to your perl's @INC path:
|
|
# a. This is one of the paths listed in: perl -e 'print join ("\n", @INC) . "\n"'
|
|
# -OR-
|
|
# b. set PERL5LIB to include the gen-perl/ directory
|
|
# 3. Execute perl DemoClient.pl.
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
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;
|
|
|