Advertisement
DRVTiny

RedC object class

May 23rd, 2017
238
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 3.73 KB | None | 0 0
  1. #!/usr/bin/perl
  2. package RedC;
  3. use strict;
  4. #use warnings;
  5. use utf8;
  6. binmode $_=>':utf8' for *STDOUT,*STDERR;
  7. use 5.16.1;
  8.  
  9. use Redis::Fast;
  10. use CBOR::XS;
  11. use Data::Dumper;
  12. use Carp qw(confess);
  13.  
  14. my %conoBy;
  15. my %redisCanDoThis;
  16. my $redTestObj;
  17. my $cbor=CBOR::XS->new;
  18.  
  19. sub new {
  20.     my ($class,$coName,$conIndex)=@_;
  21.    
  22.     my %props=('name'=>$coName,'index'=>$conIndex);
  23.     for (map [each %props], 1..keys %props) {
  24.         confess "$_->[1] already used as $_->[0]" if $conoBy{$_->[0]}{$_->[1]}
  25.     }
  26.    
  27.     my $redC=new Redis::Fast (
  28.         'reconnect'=>3,
  29.         'every'=>100_000,
  30.         'on_connect'=>sub {
  31.             $_[0]->select($conIndex);
  32.         });
  33.    
  34.     my @me=($coName,$conIndex,\$redC);
  35.     $redTestObj||=$redC;
  36.     $conoBy{'name'}{$coName}=$redC;
  37.     $conoBy{'index'}{$conIndex}=$redC;
  38.  
  39.     bless sub {
  40.         state $selfMethods={
  41.             'me'    =>  sub {
  42.                 return \@me
  43.             },
  44.             'write' =>  sub {
  45.                 my $cb=pop(@_) if ref $_[$#_] eq 'CODE';
  46.                 return unless @_;
  47.                 my $method=(@_>2?'m':'').'set';
  48.                 $redC->$method(
  49.                     (map {
  50.                         my ($k,$v)=(shift,shift);
  51.                         $k=>ref($v)
  52.                             ? $CBOR::XS::MAGIC.$cbor->encode($v)
  53.                             : $v
  54.                     } 1..+(scalar(@_)>>1)),
  55.                     $cb?($cb):()
  56.                 );
  57.             },
  58.             'read'  =>  sub {
  59.                 my $flRetHashRef=ref($_[0]) eq 'HASH'?do { shift; 1 }:undef;
  60.                 my $cb=pop(@_) if ref $_[$#_] eq 'CODE';
  61.                 return unless @_;
  62.                 my $method=($#_?'m':'').'get';
  63.                 my @k=@_;
  64.                 my $retv;
  65.                 $redC->$method(@k, sub {
  66.                     if ( defined $_[1] ) {
  67.                         if ($cb) {
  68.                             $cb->(@_)
  69.                         } else {
  70.                             confess 'Redis error: '.$_[1]
  71.                         }
  72.                     }
  73.                    
  74.                     $retv=[ map {
  75.                         ( defined($_) and length($_)>3 and substr($_,0,3) eq $CBOR::XS::MAGIC )
  76.                             ? $cbor->decode($_)
  77.                             : $_
  78.                     } ref($_[0]) eq 'ARRAY'?@{$_[0]}:($_[0]) ];
  79.                     $retv={(map {$k[$_]=>$retv->[$_]} 0..$#k)} if $flRetHashRef;
  80.                     $cb->( $retv ) if $cb;
  81.                 });
  82.                 return 1 if $cb;
  83.                 $redC->wait_all_responses;
  84.                 return $retv;
  85.             }
  86.         };
  87.         return unless my $method=shift;
  88.         return if ref $method;
  89.         return $selfMethods->{$_[0]} if $method eq 'hasMethod';
  90.         if (my $hndl=$selfMethods->{$method}) {
  91.             return $hndl->(@_)
  92.         }
  93.         $redC->$method(@_)
  94.     }, (ref $class || $class);
  95. }
  96.  
  97. sub AUTOLOAD {
  98.     our $AUTOLOAD;
  99.     my $slf=$_[0];
  100.        
  101.     return unless my ($method)=$AUTOLOAD=~/::(\w+)$/;
  102.     unless ($slf->('hasMethod', $method) or $redisCanDoThis{$method}) {
  103.         confess 'Redis method "select" is prohibited for '.__PACKAGE__.' objects'
  104.             if $method eq 'select';
  105.         eval { $redTestObj->$method() };
  106.         confess 'Redis cant do <<'.$method.'>>' if $@ and index($@,'unknown command')>=0;
  107.         $redisCanDoThis{$method}=1
  108.     }
  109.     {
  110.         no strict 'refs';
  111.         *{$AUTOLOAD}=sub {
  112.             $slf->($method, @_[1..$#_]);
  113.         }        
  114.     }
  115.     goto &{$AUTOLOAD};
  116. }
  117.  
  118. sub DESTROY {
  119.     my $slf=shift;
  120.     my @iam=@{$slf->('me')};
  121.     delete $conoBy{'name'}{$iam[0]};
  122.     delete $conoBy{'index'}{$iam[1]};
  123.     undef ${$iam[2]};
  124. }
  125.  
  126. 1;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement