Advertisement
DRVTiny

RedC object class, v0.12

May 25th, 2017
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 5.03 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. use Exporter qw(import);
  14. our @EXPORT_OK=qw(get_redc_by);
  15.  
  16. my %conoByName;
  17. my %redisCanDoThis;
  18. my $redTestObj=Redis::Fast->new('reconnect'=>3,'every'=>100_000);
  19. my $cbor=CBOR::XS->new;
  20.  
  21. sub new {
  22.     my ($class,$coName,$conIndex)=@_;
  23.     $conIndex=0 unless defined $conIndex and $conIndex!~/[^\d]/;
  24.     my %props=('name'=>$coName,'index'=>$conIndex);
  25.     confess "$coName already used as Redis connector name" if $conoByName{$coName};
  26.     if ($conIndex) {
  27.         my $nDB=__databases($redTestObj);
  28.         confess sprintf('Redis database index #%s is out of configured bounds (min=0, max=%d)',$conIndex,$nDB-1)
  29.             if $conIndex>=$nDB;
  30.     }
  31.     my $redC=Redis::Fast->new(
  32.         'reconnect'=>3,
  33.         'every'=>100_000,
  34.         $conIndex
  35.             ? ('on_connect'=>sub {
  36.                     $_[0]->select($conIndex);
  37.               })
  38.             : ()
  39.     );
  40.    
  41.     my %props=('name'=>$coName,'index'=>$conIndex,'redc'=>\$redC);
  42.    
  43.     my $cono=bless sub {
  44.         state $selfMethods={
  45.             'me'    =>  sub {
  46.                 return \%props
  47.             },
  48.             'select'    =>  sub {
  49.                 confess 'Redis method "select" is prohibited for '.__PACKAGE__.' objects'
  50.             },
  51.             'write' =>  sub {
  52.                 my $cb=pop(@_) if ref $_[$#_] eq 'CODE';
  53.                 return unless @_;
  54.                 my $method=(@_>2?'m':'').'set';
  55.                 $redC->$method(
  56.                     (map {
  57.                         my ($k,$v)=(shift,shift);
  58.                         $k=>ref($v)
  59.                             ? $CBOR::XS::MAGIC.$cbor->encode($v)
  60.                             : do { utf8::encode($v) if utf8::is_utf8($v); $v }
  61.                     } 1..+(scalar(@_)>>1)),
  62.                     $cb?($cb):()
  63.                 );
  64.             },
  65.             'read'  =>  sub {
  66.                 my $flRetHashRef=ref($_[0]) eq 'HASH'?do { shift; 1 }:undef;
  67.                 my $cb=pop(@_) if ref $_[$#_] eq 'CODE';
  68.                 return unless @_;
  69.                 my $method=($#_?'m':'').'get';
  70.                 my @k=@_;
  71.                 my $retv;
  72.                 $redC->$method(@k, sub {
  73.                     if ( defined $_[1] ) {
  74.                         if ($cb) {
  75.                             $cb->(@_)
  76.                         } else {
  77.                             confess 'Redis error: '.$_[1]
  78.                         }
  79.                     }
  80.                    
  81.                     $retv=[ map {
  82.                         ( defined($_) and length($_)>3 and substr($_,0,3) eq $CBOR::XS::MAGIC )
  83.                             ? $cbor->decode($_)
  84.                             : do { utf8::decode($_); $_ }
  85.                     } ref($_[0]) eq 'ARRAY'?@{$_[0]}:($_[0]) ];
  86.                     $retv={(map {$k[$_]=>$retv->[$_]} 0..$#k)} if $flRetHashRef;
  87.                     $cb->( $retv ) if $cb;
  88.                 });
  89.                 return 1 if $cb;
  90.                 $redC->wait_all_responses;
  91.                 return $retv;
  92.             },
  93.             'databases' =>  sub {
  94.                 __databases($redC);
  95.             },
  96.         };
  97.         return unless my $method=shift;
  98.         return if ref $method;
  99.         return $selfMethods->{$_[0]} if $method eq 'hasMethod';
  100.         if (my $hndl=$selfMethods->{$method}) {
  101.             return $hndl->(@_)
  102.         }
  103.         $redC->$method(@_)
  104.     }, (ref $class || $class);    
  105.  
  106.     $conoByName{$coName}={'name'=>$coName,'index'=>$conIndex,'cono'=>$cono};
  107.     return $cono;
  108. }
  109.  
  110. sub __databases {
  111.     my $r=shift;
  112.     return unless ref($r)=~m/^Redis(?:::Fast)?$/;
  113.     open my $fh, '<', $r->info->{'config_file'};
  114.     ((local $/=<$fh>)=~m/(?:^|\n)\s*databases\s+(\d+)\s*(?:$|\n)/sm)[0];
  115. }
  116.  
  117. sub get_redc_by {
  118.     shift if ref $_[0] eq __PACKAGE__;
  119.     my $byWhat=shift;
  120.     return if ref $byWhat or !defined($byWhat);
  121.     given ($byWhat) {
  122.         return $conoByName{$byWhat}
  123.             when 'name';
  124.         return [grep {$_->{'index'}==$byWhat} values %conoByName]
  125.             when 'index';
  126.         default {
  127.             confess 'No such connector object attribute: '.$byWhat
  128.         }
  129.     }
  130. }
  131.  
  132. sub AUTOLOAD {
  133.     our $AUTOLOAD;
  134.     my $slf=shift;
  135.     return unless my ($method)=$AUTOLOAD=~/::(\w+)$/;
  136.     unless ($slf->('hasMethod', $method)) {
  137.         unless ($redisCanDoThis{$method}) {
  138.             eval { $redTestObj->$method() };
  139.             confess 'Redis cant do <<'.$method.'>>' if $@ and index($@,'unknown command')>=0;
  140.             $redisCanDoThis{$method}=1            
  141.         }
  142.         my $redC=$slf->('me'){'redc'};
  143.         no strict 'refs';
  144.         *{$AUTOLOAD}=sub { ${$redC}->$method(@_) };
  145.     } else {
  146.         no strict 'refs';
  147.         *{$AUTOLOAD}=sub { $slf->($method, @_) };
  148.     }
  149.     goto &{$AUTOLOAD};
  150. }
  151.  
  152. sub DESTROY {
  153.     my $iam=$_[0]->('me');
  154.     delete $conoByName{$iam->{'name'}};
  155.     undef ${$iam->{'redc'}};
  156. }
  157.  
  158. 1;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement