File Coverage

blib/lib/DB/AsKVS.pm
Criterion Covered Total %
statement 15 110 13.6
branch 0 12 0.0
condition 0 10 0.0
subroutine 5 11 45.4
pod 0 6 0.0
total 20 149 13.4


line stmt bran cond sub pod time code
1             package DB::AsKVS;
2 1     1   21352 use strict;
  1         3  
  1         39  
3 1     1   5 use warnings;
  1         1  
  1         30  
4 1     1   2539 use String::CRC32;
  1         2440  
  1         70  
5 1     1   4401 use DBI;
  1         23242  
  1         71  
6 1     1   1210 use Cache::Memcached::Fast;
  1         11327  
  1         2410  
7             #use Data::Dumper::Concise;
8              
9             our $VERSION = '0.02';
10              
11             sub new{
12 0     0 0   my ($this, $p) = @_;
13 0           my $self = {
14             p => $p,
15             };
16 0           return bless($self, $this);
17             }
18              
19             # for Public Function
20             sub create{
21 0     0 0   my ($self, $rk) = @_;
22 0           for my $h (@{$self->{p}->{rdbms}}){
  0            
23             =pod
24             my $dbh = DBI->connect(
25             "dbi:" . $_->{driver} . ":dbname=" . $_->{dbname} . ";host=" . $_->{host} . ";port=" . $_->{port},
26             $_->{uid},
27             $_->{pwd},
28             $_->{opt},
29             ) || die $!;
30             =cut
31 0           my $dsn = "dbi:" . $h->{driver} . ":" . join(";", map{$_ .= "=" . $h->{$_}; $_} grep{$_ !~ /driver|uid|pwd|opt/;} keys %{$h});
  0            
  0            
  0            
  0            
32 0   0       my $dbh = DBI->connect($dsn, $h->{uid}, $h->{pwd}, $h->{opt}) ||die $!;
33 0           $dbh->do("create table " . $rk . " (k varchar(100), t int, v blob, f boolean, key index_rk_k(k))engine=innoDB");
34 0           $dbh->disconnect;
35             }
36             }
37              
38             sub put{
39 0     0 0   my ($self, $rk, $k, $v) = @_;
40 0           my $rdbms = $self->{p}->{rdbms}->[crc32($rk . "_" . $k)%scalar(@{$self->{p}->{rdbms}})];
  0            
41 0           my $memcached = $self->{p}->{memcached}->[crc32($rk . "_" . $k)%scalar(@{$self->{p}->{memcached}})];
  0            
42 0           my $mem = new Cache::Memcached::Fast({
43             servers => [$memcached->{host} . ":" . $memcached->{port}],
44             });
45 0           $self->remove($rk,$k);
46             =pod
47             my $dbh = DBI->connect(
48             "dbi:" . $rdbms->{driver} . ":dbname=" . $rdbms->{dbname} . ";host=" . $rdbms->{host} . ";port=" . $rdbms->{port},
49             $rdbms->{uid},
50             $rdbms->{pwd},
51             $rdbms->{opt},
52             ) || die $!;
53             =cut
54 0           my $dsn = "dbi:" . $rdbms->{driver} . ":" . join(";", map{$_ .= "=" . $rdbms->{$_}; $_} grep{$_ !~ /driver|uid|pwd|opt/;} keys %{$rdbms});
  0            
  0            
  0            
  0            
55 0   0       my $dbh = DBI->connect($dsn, $rdbms->{uid}, $rdbms->{pwd}, $rdbms->{opt}) ||die $!;
56 0           $mem->set($rk . "_" . $k, $v);
57 0           my $sth = $dbh->prepare("insert into $rk(k,t,v,f) values(?,?,?,?)");
58 0           $sth->execute($k, time(), $v, 1);
59 0           $sth->finish;
60 0           $dbh->disconnect;
61             }
62              
63             sub get{
64 0     0 0   my ($self, $rk, $k) = @_;
65 0           my $rdbms = $self->{p}->{rdbms}->[crc32($rk . "_" . $k)%scalar(@{$self->{p}->{rdbms}})];
  0            
66 0           my $memcached = $self->{p}->{memcached}->[crc32($rk . "_" . $k)%scalar(@{$self->{p}->{memcached}})];
  0            
67 0           my $mem = new Cache::Memcached::Fast({
68             servers => [$memcached->{host} . ":" . $memcached->{port}],
69             });
70 0           my $d = $mem->get($rk . "_" . $k);
71 0 0         if(!$d){
72             =pod
73             my $dbh = DBI->connect(
74             "dbi:" . $rdbms->{driver} . ":dbname=" . $rdbms->{dbname} .
75             ";host=" . $rdbms->{host} . ";port=" . $rdbms->{port},
76             $rdbms->{uid},
77             $rdbms->{pwd},
78             $rdbms->{opt},
79             ) || die $!;
80             =cut
81 0           my $dsn = "dbi:" . $rdbms->{driver} . ":" . join(";", map{$_ .= "=" . $rdbms->{$_}; $_} grep{$_ !~ /driver|uid|pwd|opt/;} keys %{$rdbms});
  0            
  0            
  0            
  0            
82 0   0       my $dbh = DBI->connect($dsn, $rdbms->{uid}, $rdbms->{pwd}, $rdbms->{opt}) ||die $!;
83 0           my $sth->prepare("select v from $rk where k=? and f=1 order by t desc");
84 0           $sth->execute($k);
85 0           while(my $r = $sth->fetchrow_arrayref){
86 0 0         my @tmp = map{$_ = $_?$_:'';} @{$r};
  0            
  0            
87 0           $d = $tmp[0];
88 0 0         last if($d);
89             }
90 0 0         $mem->set($rk . "_" . $k, $d) if($d);
91 0           $sth->finish;
92 0           $dbh->disconnect;
93             }
94 0           return $d;
95             }
96              
97             sub get_multi{
98 0     0 0   my ($self, $rk, $k) = @_;
99 0           my $d;
100 0           for my $h (@{$self->{p}->{rdbms}}){
  0            
101             =pod
102             my $dbh = DBI->connect(
103             "dbi:" . $_->{driver} . ":dbname=" . $_->{dbname} . ";host=" . $_->{host} . ";port=" . $_->{port},
104             $_->{uid},
105             $_->{pwd},
106             $_->{opt},
107             ) || die $!;
108             =cut
109 0           my $dsn = "dbi:" . $h->{driver} . ":" . join(";", map{$_ .= "=" . $h->{$_}; $_} grep{$_ !~ /driver|uid|pwd|opt/;} keys %{$h});
  0            
  0            
  0            
  0            
110 0   0       my $dbh = DBI->connect($dsn, $h->{uid}, $h->{pwd}, $h->{opt}) ||die $!;
111 0           my $sth = $dbh->prepare("select * from $rk where k like ? and f=1");
112 0           $sth->execute($k . '%');
113 0           while(my $r = $sth->fetchrow_arrayref){
114 0 0         my @tmp = map{$_ = $_?$_:''} @{$r};
  0            
  0            
115 0           $d->{$rk . "_" . $tmp[0]} = $tmp[2];
116             }
117 0           $sth->finish;
118 0           $dbh->disconnect;
119             }
120 0           return $d;
121             }
122              
123             sub remove{
124 0     0 0   my ($self, $rk, $k) = @_;
125 0           my $rdbms = $self->{p}->{rdbms}->[crc32($rk . "_" . $k)%scalar(@{$self->{p}->{rdbms}})];
  0            
126 0           my $memcached = $self->{p}->{memcached}->[crc32($rk . "_" . $k)%scalar(@{$self->{p}->{memcached}})];
  0            
127 0           my $mem = new Cache::Memcached::Fast({
128             servers => [$memcached->{host} . ":" . $memcached->{port}],
129             });
130 0 0         $mem->delete($rk . "_" . $k) if($mem->get($rk . "_" . $k));
131             =pod
132             my $dbh = DBI->connect(
133             "dbi:" . $rdbms->{driver} . ":dbname=" . $rdbms->{dbname} . ";host=" . $rdbms->{host} . ";port=" . $rdbms->{port},
134             $rdbms->{uid},
135             $rdbms->{pwd},
136             $rdbms->{opt},
137             ) || die $!;
138             =cut
139 0           my $dsn = "dbi:" . $rdbms->{driver} . ":" . join(";", map{$_ .= "=" . $rdbms->{$_}; $_} grep{$_ !~ /driver|uid|pwd|opt/;} keys %{$rdbms});
  0            
  0            
  0            
  0            
140 0   0       my $dbh = DBI->connect($dsn, $rdbms->{uid}, $rdbms->{pwd}, $rdbms->{opt}) ||die $!;
141 0           my $sth = $dbh->prepare("update $rk set f=0 where k=?");
142 0           $sth->execute($k);
143 0           $sth->finish;
144 0           $dbh->disconnect;
145             }
146              
147             1;
148              
149             =head1 NAME
150              
151             DB::AsKVS - This module is using RDBMS as KVS.
152              
153             =head1 SYNOPSIS
154              
155             #!/usr/bin/perl
156             use strict;
157             use warnings;
158             use DB::AsKVS;
159              
160             my $param = {
161             rdbms => [
162             {
163             driver => 'mysql',
164             dbname => 'demo',
165             host => 'localhost',
166             port => 3306,
167             uid => 'root',
168             pwd => 'password',
169             opt => {},
170             },
171             ],
172             memcached => [
173             {
174             host => 'localhost',
175             port => 11211,
176             },
177             ],
178             };
179             my $db = new DB::AsKVS($param);
180             $db->create("RowKey");
181             $db->put("RowKey", "Key", "Value");
182             print $db->get("RowKey", "Key");
183              
184             =head1 DISCRIPTION
185              
186             The DB::AsKVS module can use RDBMS as KVS.
187             To use this module, You will be able to design architecture for scale out.
188              
189             =head1 Usage
190            
191             Constructor
192              
193             my $db = new DB::AsKVS($param);
194             * $param is parameter of RDBMS and Memcached.
195             Please show SYNOPSIS section.
196              
197             Methods
198              
199             $db->create("RowKey");
200             Create the RowKey.
201              
202             $db->put("RowKey", "Key", "Value");
203             insert data.
204              
205             my $return_vaule = $db->get("RowKey", "Key");
206             This method pick up the data for matching "RowKey" and "Key".
207             $return_value is scalar value.
208              
209             my $return_value = $db->get_multi("RowKey", "Part of Key value");
210             This method pick up the data for matching "RowKey" and "Key".
211             $return_value is hash reference of Key and Value.
212              
213             $db->remove("RowKey", "Key");
214             This method is deleteing data for matching "RowKey" and "Key".
215              
216             =head1 Copyright
217              
218             Kazunori Minoda (C)2013
219              
220             =cut
221