File Coverage

blib/lib/IPC/Lite.pm
Criterion Covered Total %
statement 345 446 77.3
branch 154 234 65.8
condition 11 23 47.8
subroutine 42 47 89.3
pod 2 22 9.0
total 554 772 71.7


line stmt bran cond sub pod time code
1             package IPC::Lite;
2              
3             # Combination of vars.pm, Tie::DBI, and IPC
4             # Wanted to called it "shared" .... ie: "use shared qw($var)"
5             # but shared memory is sketchy at best, whereas SQLite works
6             # on most platforms
7              
8             our $VERSION = '0.5.' . [qw$Revision: 40 $]->[1];
9              
10 8     8   4087494 use warnings::register;
  8         22  
  8         1480  
11 8     8   52 use strict;
  8         14  
  8         294  
12              
13             #use strict qw(vars subs);
14              
15 8     8   23983 use DBI;
  8         190180  
  8         605  
16 8     8   10947 use DBD::SQLite;
  8         4534558  
  8         1390  
17              
18             # Can set this directly if desired
19              
20             our %DEFAULT_PATH;
21             our %DEFAULT_TTL;
22             our %DEFAULT_KEY;
23             our $DEBUG;
24              
25             my %DBS;
26              
27             #$SIG{__DIE__} = \&fatalerror;
28              
29             # this code from vars.pm, since we can't adjust the "callpack"
30             sub import {
31             #hereiam();
32 11     11   123 my $callpack = caller;
33 11         46 my ($pack, @imports) = @_;
34 11         116 my ($sym, $ch, $sym_n);
35 0         0 my %opts;
36            
37 0         0 my $imps;
38            
39 11         28 my $i = -1;
40 11         34 foreach (@imports) {
41 22         33 ++$i;
42 22 100       208 if (($ch, $sym) = /^([\$\@\%])(.+)/) {
43 8     8   78 no strict 'refs';
  8         18  
  8         287  
44 8     8   40 no warnings 'uninitialized';
  8         14  
  8         49297  
45 15 50       113 if ($sym =~ /\W/) {
46             # time for a more-detailed check-up
47 0 0 0     0 if ($sym =~ /^\w+[[{].*[]}]$/) {
    0 0        
    0          
48 0         0 require Carp;
49 0         0 Carp::croak("Can't declare individual elements of hash or array");
50             } elsif (warnings::enabled() and length($sym) == 1 and $sym !~ tr/a-zA-Z//) {
51 0         0 warnings::warn("No need to declare built-in vars");
52             } elsif (($^H &= strict::bits('vars'))) {
53 0         0 require Carp;
54 0         0 Carp::croak("'$_' is not a valid variable name under strict vars");
55             }
56             }
57             # don't put "main::" on every table entry, too ugly
58 15         27 $sym_n = $sym;
59 15 50       72 $sym = "${callpack}::$sym" unless $sym =~ /::/;
60 15 50       46 $sym_n = $sym unless $callpack eq 'main';
61             *$sym =
62             ( $ch eq "\$" ? \$$sym
63             : $ch eq "\@" ? \@$sym
64             : $ch eq "\%" ? \%$sym
65 15 50       138 : do {
    100          
    100          
66 0         0 require Carp;
67 0         0 Carp::croak("'$_' is not a valid variable name");
68             });
69 15         1240 eval("tie ${ch}$sym, '$pack', \%opts, sym=>'$sym_n';");
70 15 50       86 if ($@) {
71 0         0 require Carp;
72 0         0 Carp::croak("'$_' problem with tie: $@");
73             }
74 15         80 ++$imps;
75             } else {
76 7 100       121 if ($_ =~ /^(ttl|timeout)$/i) {
77 1         3 $opts{ttl} = splice @imports, $i+1, 1;
78 1 50       6 $opts{ttl} = $1 if $opts{ttl} =~ s/\s*\b(\d+)(s|\s*seconds)\b\s*//;
79 1 0       4 $opts{ttl} = 86400 * $1 + ($opts{ttl} ? $opts{ttl} : 0) if $opts{ttl} =~ s/\s*\b(\d+)(d|\s*days)\b\s*//;
    50          
80 1         3 next;
81             }
82 6 50       44 if ($_ =~ /^path$/i) {
83 6         36 $opts{path} = splice @imports, $i+1, 1;
84 6         25 next;
85             }
86 0 0       0 if ($_ =~ /^key$/i) {
87 0         0 $opts{key} = splice @imports, $i+1, 1;
88 0         0 next;
89             }
90 0         0 require Carp;
91 0         0 Carp::croak("'$_' is not a valid variable name for $pack");
92             }
93             }
94              
95             # assume user wanted to set global defaults instead
96 11 100       9574 if (!$imps) {
97 4 100       20 $DEFAULT_PATH{$callpack} = $opts{path} if $opts{path};
98 4 50       16 $DEFAULT_TTL{$callpack} = $opts{ttl} if $opts{ttl};
99 4 50       1837 $DEFAULT_KEY{$callpack} = $opts{key} if $opts{key};
100             }
101             };
102              
103              
104             #### public methods
105              
106             sub path {
107 0     0 1 0 return $_[0]->{path};
108             }
109              
110             sub db {
111 0     0 1 0 return $_[0]->{db};
112             }
113              
114             #### create tables
115              
116             sub create_vars_table {
117 1     1 0 3 my ($db) = @_;
118 1         4 create_table($db, "vars", "(styp text, sym text int, exp int, primary key (styp, sym))");
119             }
120              
121             sub create_scalar_table {
122 9     9 0 19 my ($db) = @_;
123 9         78 create_table($db, "scalar","(sym text primary key, val text, vtyp text)");
124             }
125              
126             sub create_array_table {
127 5     5 0 8 my ($db) = @_;
128 5         16 create_table($db, "array", "(sym text, ind int, val text, vtyp text, primary key (sym, ind));")
129             }
130              
131             sub create_hash_table {
132 4     4 0 6 my ($db) = @_;
133 4         17 create_table($db, "hash" , "(sym text, key text, val text, vtyp text, primary key (sym, key));");
134             }
135              
136             sub create_hash_subtable {
137 1     1 0 2 my ($db, $name) = @_;
138 1         3 create_table($db, $name, "(key text primary key, val text, vtyp text);");
139             }
140              
141             sub create_array_subtable {
142 1     1 0 3 my ($db, $name) = @_;
143 1         5 create_table($db, $name, "(ind text primary key, val text, vtyp text);");
144             }
145              
146              
147             sub create_table {
148 21     21 0 47 my ($db, $name, $fds) = @_;
149 21         219 $db->do("create table if not exists $name $fds");
150 21         85101 return 1;
151             }
152              
153             ## connect to db
154              
155             sub open_pathdb {
156 23     23 0 47 my ($self) = @_;
157 23         66 my $path = $self->{path};
158 23         62 my $db = {};
159 23         82 my $tid = threadid();
160 23 100       167 if (!($db = $DBS{$tid}{$path})) {
161 9         24 my $connstr;
162 9         202 $db = DBI->connect("dbi:SQLite:dbname=$path", "", "", {PrintError=>0, AutoCommit=>1});
163 9 50       21508 if ($db) {
164 9         132 $db->{PrintError} = 0;
165             } else {
166 0         0 require Carp;
167 0         0 Carp::croak("Can't create db at $path: " . DBI->errstr);
168             }
169 9         53 $db->{RaiseError} = 1;
170 9         42 $DBS{$tid}{$path} = $db;
171             }
172 23         112 $self->{tid} = $tid;
173 23         65 $self->{db} = $db;
174             }
175              
176             # get caller's package... ignoring IPC::Lite
177              
178             sub getcallpack {
179 19     19 0 31 my $self = shift;
180 19         42 my ($callpack, $callframe) = ('', 2);
181              
182 19         1428 while (($callpack = scalar caller($callframe)) eq ref($self)) {
183 32         90 ++$callframe;
184             }
185 19         46 return $callpack;
186             }
187              
188             # generic tie_var, called by TIESCALAR, TIEHASH, TIEARRAY
189              
190             sub tie_var {
191 20     20 0 42 my $type = shift;
192 20         30 my $pack = shift;
193              
194 20         42 my $self = {};
195              
196 20         111 my %opts = @_;
197 20         68 for (keys(%opts)) {
198 46         146 $self->{lc($_)} = $opts{$_};
199             }
200              
201 20         57 bless $self, $pack;
202 20         107 $self->{type} = $type;
203              
204 20         28 my $callpack;
205              
206             # get package defaults
207              
208 20 100       71 if (!defined($self->{ttl})) {
209 19 50       106 $callpack = $self->getcallpack() unless $callpack;
210 19         49 $self->{ttl} = $DEFAULT_TTL{$callpack};
211             }
212              
213             # if there's no path or key, check for default key
214 20 50 66     89 if (!$self->{path} && !$self->{key}) {
215 11 50       22 $callpack = $self->getcallpack() unless $callpack;
216 11         25 $self->{key} = $DEFAULT_KEY{$callpack};
217             }
218              
219 20 50       55 if ($self->{key}) {
220 0         0 $self->{path} = nametopath($self->{key});
221 0         0 delete $self->{key}; # don't inherit
222             }
223              
224             # still no path, get default path
225 20 100       58 if (!$self->{path}) {
226 11 50       29 $callpack = $self->getcallpack() unless $callpack;
227 11         33 $self->{path} = $self->defaultpath($callpack);
228             };
229              
230 20         67 $self->open_pathdb();
231              
232 20 100       67 if ($self->{sym}) {
    50          
233 18 50       51 print "tie: '$self->{sym}' styp '$self->{type}'\n" if $DEBUG;
234 18 100       54 if ($self->{ttl}) {
235 1         5 create_vars_table($self->{db});
236 1         24 my $exp = time() + $self->{ttl};
237 1         6 my $up = $self->dbexec('refincr', "update vars set exp=? where sym=? and styp=?",
238             $exp, $self->{sym}, $self->{type});
239 1 50       19 if ($up == 0) {
240 0         0 $self->dbexec('refins', "insert into vars (sym, styp, exp) values (?, ?, ?);",
241             $self->{sym}, $self->{type}, $exp);
242             }
243             }
244             } elsif ($self->{table}) {
245 2 50       9 if ($self->{type} eq '$') {
246 0         0 require Carp;
247 0         0 croak("Won't bind scalar to its own table");
248             }
249 2 50       9 print "tie: '$self->{table}' styp '$self->{type}'\n" if $DEBUG;
250             } else {
251 0         0 require Carp;
252 0         0 Carp::croak("Need sym or table for IPC::Lite");
253             }
254              
255 20         83 return $self;
256             }
257              
258             sub cleanup {
259 1     1 0 17 for my $tid_dbs (values(%DBS)) {
260 1         8 for my $db (values(%$tid_dbs)) {
261 1         11 my $st = dbexec($db, 'cleanup1', "select sym, styp from vars where exp > 0 and exp < ?", time());
262 1         43 while (my $row=$st->fetchrow_arrayref()) {
263 1         6 my ($sym, $styp) = @$row;
264 1 50       9 print "cleanup: $sym, $styp\n" if $DEBUG;
265 1 50       7 if ($styp eq '$') {
    0          
    0          
266 1         6 dbexec($db, 'clearscalar', "delete from scalar where sym=?", $sym);
267             } elsif ($styp eq '%') {
268 0         0 dbexec($db, 'clearhash', "delete from hash where sym=?", $sym);
269             } elsif ($styp eq '@') {
270 0         0 dbexec($db, 'cleararray', "delete from array where sym=?", $sym);
271             }
272             }
273             }
274             }
275             }
276              
277             sub TIESCALAR {
278             #hereiam();
279 9     9   41 my $self = tie_var('$', @_);
280 9         58 create_scalar_table($self->{db});
281 9         126 return $self;
282             }
283              
284             sub TIEHASH {
285             #hereiam();
286 5     5   1446 my $self = tie_var('%', @_);
287 5 100       22 if ($self->{sym}) {
    50          
288 4         17 create_hash_table($self->{db});
289             } elsif ($self->{table}) {
290 1         5 create_hash_subtable($self->{db}, $self->{table});
291             } else {
292 0         0 require Carp;
293 0         0 Carp::croak("Need table or sym for explicit tie");
294             }
295 5         25 return $self;
296             }
297              
298             sub TIEARRAY {
299             #hereiam();
300 6     6   33 my $self = tie_var('@', @_);
301 6 100       21 if ($self->{sym}) {
    50          
302 5         15 create_array_table($self->{db});
303             } elsif ($self->{table}) {
304 1         5 create_array_subtable($self->{db}, $self->{table});
305             } else {
306 0         0 require Carp;
307 0         0 Carp::croak("Need table or sym for explicit tie");
308             }
309 6         63 return $self;
310             }
311              
312              
313             sub canonical {
314             #hereiam();
315 3     3 0 6 my ($self, $key) = @_;
316 3         11 $self->checkdb();
317 3         4 my $canon;
318              
319 3 50       25 if ($self->{sym}) {
320 3         11 $canon = '$' . $self->{sym};
321             } else {
322 0         0 $canon = '#' . $self->{table};
323             }
324              
325 3 50       20 if ($self->{type} eq '%') {
    50          
326 0         0 $canon .= '{' . $key . '}';
327             } elsif ($self->{type} eq '@') {
328 0         0 $canon .= '[' . $key . ']';
329             }
330              
331 3         9 return $canon;
332             }
333              
334             sub FIRSTKEY {
335             #hereiam();
336 4     4   8 my ($self) = @_;
337 4         10 $self->checkdb();
338 4 50       17 if ($self->{sym}) {
339 4         14 $self->{keyst} = $self->dbexec('enumkey', "select key, val, vtyp from hash where sym=?", $self->{sym});
340             } else {
341 0         0 $self->{keyst} = $self->dbexec('', "select key, val, vtyp from $self->{table}");
342             }
343 4         16 return $self->NEXTKEY();
344             }
345              
346             sub NEXTKEY {
347             #hereiam();
348 12     12   25 my ($self) = @_;
349 12         25 $self->checkdb();
350 12         114 my $row = $self->{keyst}->fetchrow_arrayref();
351 12 100       30 if (!$row) {
352 4         6 $self->{keyst} = undef;
353 4         20 return ();
354             }
355              
356 8         10 my ($key, $val, $vtyp) = @{$row};
  8         19  
357 8 50       17 if (wantarray) {
358 0         0 return ($key, tiesubrefs($self, $key, $val, $vtyp));
359             } else {
360 8         83 return $key;
361             }
362             }
363              
364             sub CLEAR {
365             #hereiam();
366 6     6   56 my ($self) = @_;
367 6         33 $self->checkdb();
368 6 100       27 if ($self->{sym}) {
369 5 50       41 if ($self->{type} eq '%') {
    50          
370 0         0 $self->dbexec('clearhash', "delete from hash where sym=?", $self->{sym});
371             } elsif ($self->{type} eq '@') {
372 5         27 $self->dbexec('cleararray', "delete from array where sym=?", $self->{sym});
373             }
374             } else {
375 1         9 $self->dbexec('', "delete from $self->{table}");
376             }
377             }
378              
379             sub SPLICE {
380             #hereiam();
381 4     4   14 my ($self, $offset, $length, @new) = @_;
382 4         16 $self->checkdb();
383 4 50       17 $offset = 0 unless defined $offset;
384 4 50       12 $length = $self->FETCHSIZE() - $offset unless defined $length;
385              
386 4         71 my @ret;
387              
388 4         57 $self->{db}->begin_work();
389              
390 4         102 my $n = 0;
391 4   66     26 while (@new && $length > 0) {
392             # replace
393 0         0 push @ret, $self->FETCH($offset);
394 0         0 $self->STORE($offset, $new[$n]);
395 0         0 $offset += 1;
396 0         0 $length -= 1;
397 0         0 ++$n;
398             }
399              
400             # either new was more or length was more
401 4 100       19 if ($n <= $#new) {
    50          
402 2         8 for (my $i=($self->FETCHSIZE-1); $i >= $offset; --$i) {
403             # constraints prevent us from doing this in 1 call to the db, consider turning them off for speed?
404 4 100       19 if ($self->{sym}) {
405 2         12 $self->dbexec('arrayind', "update array set ind=ind+? where sym=? and ind = ?", scalar @new, $self->{sym}, $i);
406             } else {
407 2         18 $self->dbexec('arrayind.' . $self->{table}, "update $self->{table} set ind=ind+? where ind = ?", scalar @new, $i);
408             }
409             }
410 2         14 for (; $n <= $#new; ++$n) {
411 2         24 $self->STORE($n + $offset, $new[$n]);
412             }
413             } elsif ($length > 0) {
414 2         10 for ( my $i = $offset ; $i < ( $offset + $length ) ; ++$i ) {
415 2         13 push @ret, $self->FETCH($i);
416             }
417 2 100       11 if ($self->{sym}) {
418 1         5 $self->dbexec('delarrayrange', "delete from array where sym=? and ind>=? and ind < ?",
419             $self->{sym}, $offset, $offset + $length);
420             } else {
421 1         7 $self->dbexec('', "delete from $self->{table} where ind>=? and ind < ?",
422             $offset, $offset + $length);
423             }
424             # shift indexes down in storage
425 2         27 for (my $i = $offset+1; $i < $self->FETCHSIZE; ++$i) {
426 2 100       8 if ($self->{sym}) {
427 1         4 $self->dbexec('indarray', "update array set ind=ind-? where sym=? and ind=?",
428             $length, $self->{sym}, $i);
429             } else {
430 1         7 $self->dbexec('indarray.' . $self->{table}, "update $self->{table} set ind=ind-? where ind=?",
431             $length, $i);
432             }
433             }
434             }
435              
436 4         752471 $self->{db}->commit();
437              
438 4 100       123 return wantarray ? @ret : $ret[@ret];
439             }
440              
441             sub SHIFT {
442 2     2   1986 my ($self) = @_;
443 2         11 my @val = $self->SPLICE( 0, 1 );
444 2         35 return $val[0];
445             }
446              
447             sub DELETE {
448 0     0   0 my ($self, $key) = @_;
449 0         0 $self->checkdb();
450 0 0       0 if ($self->{type} eq '%') {
451 0 0       0 if ($self->{sym}) {
452 0         0 $self->dbexec('delhash', "delete from hash where sym=? and key=?", $self->{sym}, $key);
453             } else {
454 0         0 $self->dbexec('', "delete from $self->{table} where key=?", $key);
455             }
456             } else {
457 0         0 $self->store($key, undef);
458             }
459             }
460              
461             sub FETCHSIZE {
462 33     33   1012119 my ($self) = @_;
463 33         170 $self->checkdb();
464 33         70 my $st;
465 33 100       139 if ($self->{sym}) {
466 19         111 $st = $self->dbexec('arraysize', "select max(ind) from array where sym=?", $self->{sym});
467             } else {
468 14         116 $st = $self->dbexec('', "select max(ind) from $self->{table}");
469             }
470 33         992 my ($ind) = $st->fetchrow_array();
471 33 100       1290 return defined $ind ? ($ind+1) : 0;
472             }
473              
474             sub EXTEND {
475             #hereiam();
476 6     6   28 my ($self, $count) = @_;
477 6         42 $self->checkdb();
478 6 50       51 if ($count >= 0) {
479 6 100       37 if ($self->{sym}) {
480 5         37 $self->dbexec('extarray', "delete from array where sym=? and ind >= ?", $self->{sym}, $count);
481             } else {
482 1         16 $self->dbexec('', "delete from $self->{table} where ind >= ?", $count);
483             }
484             }
485             }
486              
487             sub POP {
488 2     2   6 my ($self) = @_;
489 2         6 $self->checkdb();
490 2         22 $self->{db}->begin_work();
491 2         57 my $ind = $self->FETCHSIZE()-1;
492 2         12 my $val = $self->FETCH($ind);
493 2 100       16 if ($self->{sym}) {
494 1         5 $self->dbexec('arraypop', "delete from array where sym=? and ind = ?", $self->{sym}, $ind);
495             } else {
496 1         8 $self->dbexec('', "delete from $self->{table} where ind = ?", $ind);
497             }
498 2         43607 $self->{db}->commit();
499 2         45 return $val;
500             }
501              
502             sub PUSH {
503 6     6   4765008 my ($self, @list) = @_;
504 6         50 $self->checkdb();
505 6         280 $self->{db}->begin_work();
506 6         192 for (@list) {
507 6         18 my $st;
508 6 100       47 if ($self->{sym}) {
509 5         45 $self->dbexec('arraypush', "insert into array (sym, ind) values (?, (select 1+coalesce(max(ind),-1) from array where sym=?))", $self->{sym}, $self->{sym});
510 5         33 $st = $self->dbexec('maxind', "select max(ind) from array where sym=?", $self->{sym});
511             } else {
512 1         14 $self->dbexec('arraypush.' . $self->{table}, "insert into $self->{table} (ind) values ((select 1+coalesce(max(ind),-1) from $self->{table}))");
513 1         16 $st = $self->dbexec('maxind.' . $self->{table}, "select max(ind) from $self->{table}");
514             }
515 6         88 my ($key) = $st->fetchrow_array();
516 6         70 $self->STORE($key, $_);
517             }
518 6         883113 $self->{db}->commit();
519 6         168 return $self->FETCHSIZE();
520             }
521              
522             sub UNSHIFT {
523 2     2   8 my ($self, @list) = @_;
524 2         105 $self->checkdb();
525 2         11 return $self->SPLICE(0, 0, @list);
526             }
527              
528              
529             sub EXISTS {
530 1     1   1908 my ($self, $key) = @_;
531 1         5 return $self->FETCH($key, 'EXISTS');
532             }
533              
534             sub FETCH {
535 59     59   17588858 my ($self, $key, $act) = @_;
536 59         348 $self->checkdb();
537              
538 59         89 my $st;
539              
540 59 100       420 if ($self->{type} eq '$') {
    100          
    50          
541 23         136 $st = $self->dbexec('fetchscalar', "select val, vtyp from scalar where sym=?", $self->{sym});
542             } elsif ($self->{type} eq '%') {
543 10 100       27 if ($self->{sym}) {
544 8         25 $st = $self->dbexec('fetchhash', "select val, vtyp from hash where sym=? and key=?",
545             $self->{sym}, $key);
546             } else {
547 2         13 $st = $self->dbexec('', "select val, vtyp from $self->{table} where key=?", $key);
548             }
549             } elsif ($self->{type} eq '@') {
550 26 100       110 if ($self->{sym}) {
551 15         80 $st = $self->dbexec('fetcharray', "select val, vtyp from array where sym=? and ind=?",
552             $self->{sym}, $key);
553             } else {
554 11         73 $st = $self->dbexec('', "select val, vtyp from $self->{table} where ind=?", $key);
555             }
556             } else {
557 0         0 die;
558             }
559            
560 59         1162 my ($val, $vtyp) = $st->fetchrow_array();
561              
562 59 100 66     281 if (defined $act && $act eq 'EXISTS') {
563 1         7 return defined $vtyp;
564             }
565              
566 58         304 return tiesubrefs($self, $key, $val, $vtyp);
567             }
568              
569             sub tiesubrefs {
570             #hereiam();
571 58     58 0 680 my ($self, $key, $val, $vtyp) = @_;
572              
573 58 100       256 return undef if ! defined $vtyp;
574              
575 50 100       170 if ($vtyp eq '$') {
576 45         722 return $val;
577             }
578              
579 5 50       21 if ($vtyp eq '*') {
580 5 50       17 $key = '' if !defined $key;
581 5 100       23 if ($self->{ref}{$key}) {
582             # already tied my ref
583 4         33 return $self->{ref}{$key};
584             } else {
585             # create a new ref
586 1         4 my $canon = canonical($self, $key);
587 1 50       6 if ($val eq '$') {
    50          
    0          
588 0         0 my $var;
589 0         0 my $sub = tie $var, ref($self), %{$self}, sym=>$canon;
  0         0  
590 0         0 $val = \$var;
591             } elsif ($val eq '%') {
592 1         3 my %var;
593 1         3 my $sub = tie %var, ref($self), %{$self}, sym=>$canon;
  1         11  
594 1         4 $val = \%var;
595             } elsif ($val eq '@') {
596 0         0 my @var;
597 0         0 my $sub = tie @var, ref($self), %{$self}, sym=>$canon;
  0         0  
598 0         0 $val = \@var;
599             } else {
600 0         0 require Carp;
601 0         0 Carp::croak("Unknown reference type '$val' in $canon");
602             }
603             }
604 1 50       4 die unless ref($val);
605 1         10 return $self->{ref}{$key}=$val;
606             }
607 0         0 return undef;
608             }
609              
610             sub STORE {
611             #hereiam();
612 25     25   274 my $self = shift;
613 25         144 $self->checkdb();
614              
615 25         53 my ($key, $val);
616              
617 25 100       1042 if ($self->{type} eq '$') {
618 8         27 ($val) = @_;
619             } else {
620 17         72 ($key, $val) = @_;
621             }
622              
623 25         52 my $vtyp;
624              
625 25 100       93 if (ref($val)) {
626 2 50       16 $key = '' if !defined $key;
627 2         10 my $canon = canonical($self, $key);
628 2         9 $self->{ref}{$key} = $val;
629 2         4 $vtyp = '*';
630 2         6 my $sub;
631 2 50       14 if (ref($val) eq 'SCALAR') {
    50          
    0          
632 0         0 my $sav = ${$val};
  0         0  
633 0         0 tie ${$val}, ref($self), %{$self}, sym=>$canon;
  0         0  
  0         0  
634 0 0       0 ${$val} = $sav if defined $sav;
  0         0  
635 0         0 $val = '$';
636             } elsif (ref($val) eq 'HASH') {
637 2         2 my %sav = %{$val};
  2         11  
638 2         4 tie %{$val}, ref($self), %{$self}, sym=>$canon;
  2         6  
  2         24  
639 2 50       12 %{$val} = %sav if %sav;
  0         0  
640 2         6 $val = '%';
641             } elsif (ref($val) eq 'ARRAY') {
642 0         0 my @sav = @{$val};
  0         0  
643 0         0 $sub = tie @{$val}, ref($self), %{$self}, sym=>$canon;
  0         0  
  0         0  
644 0 0       0 @{$val} = @sav if @sav;
  0         0  
645 0         0 $val = '@';
646             } else {
647 0         0 require Carp;
648 0         0 Carp::croak("Can't store reference to " . ref($val) . " in $canon, try Data::Dumper instead");
649             }
650             } else {
651 23         62 $vtyp = '$';
652             }
653              
654 25 50       200 if ($DEBUG) {
655 0         0 require Carp;
656 0         0 Carp::cluck "store: $self->{type}:$self->{sym}($key) = $vtyp:$val\n"
657             }
658              
659 25 100       180 if ($self->{ttl}) {
660 1         3 my $exp = time() + $self->{ttl};
661 1         6 my $up = $self->dbexec('updateexp', "update vars set exp=? where sym=? and styp=?",
662             $exp, $self->{sym}, $self->{type});
663             }
664              
665 25 100       10193 if ($self->{type} eq '$') {
    100          
    50          
666 8 100       58 if (!defined ($val)) {
667 2         12 $self->dbexec('delscalar', "delete from scalar where sym=?", $self->{sym});
668             } else {
669 6         42 my $up = $self->dbexec('updatescalar', "update scalar set val=?,vtyp=? where sym=?",
670             $val, $vtyp, $self->{sym});
671 6 100       59 if ($up == 0) {
672 2         14 $self->dbexec('insertscalar', "insert into scalar (sym, val, vtyp) values (?, ?, ?)",
673             $self->{sym}, $val, $vtyp);
674             }
675             }
676             } elsif ($self->{type} eq '%') {
677 7 100       28 if ($self->{sym}) {
678 5 50       22 if (!defined ($val)) {
679 0         0 $self->dbexec('delscalar', "delete from hash where sym=? and key=?", $self->{sym}, $key);
680             } else {
681 5         103 my $up = $self->dbexec('updatehash', "update hash set val=?,vtyp=? where sym=? and key=?",
682             $val, $vtyp, $self->{sym}, $key);
683 5 50       948 if ($up == 0) {
684 0         0 $self->dbexec('inserthash', "insert into hash (sym, key, val, vtyp) values (?, ?, ?, ?)",
685             $self->{sym}, $key, $val, $vtyp);
686             }
687             }
688             } else {
689 2 50       8 if (!defined ($val)) {
690 0         0 $self->dbexec('', "delete from $self->{table} where key=?", $key);
691             } else {
692 2         18 my $up = $self->dbexec('', "update $self->{table} set val=?,vtyp=? where key=?", $val, $vtyp, $key);
693 2 50       62 if ($up == 0) {
694 0         0 $self->dbexec('', "insert into $self->{table} (key, val, vtyp) values (?, ?, ?)",
695             $key, $val, $vtyp);
696             }
697             }
698             }
699             } elsif ($self->{type} eq '@') {
700 10 100       49 if ($self->{sym}) {
701 7         52 my $up = $self->dbexec('updatearray', "update array set val=?,vtyp=? where sym=? and ind=?",
702             $val, $vtyp, $self->{sym}, $key);
703 7 100       59 if ($up == 0) {
704 2         9 $self->dbexec('insertarray', "insert into array (sym, ind, val, vtyp) values (?, ?, ?, ?)",
705             $self->{sym}, $key, $val, $vtyp);
706             }
707             } else {
708 3         22 my $up = $self->dbexec('', "update $self->{table} set val=?,vtyp=? where ind=?", $val, $vtyp, $key);
709 3 100       61 if ($up == 0) {
710 2         14 $self->dbexec('', "insert into $self->{table} (ind, val, vtyp) values (?, ?, ?)",
711             $key, $val, $vtyp);
712             }
713             }
714             } else {
715 0         0 die "Unknown type $self->{type}\n";
716             }
717              
718 25         308 return $val;
719             }
720              
721             sub dbexec {
722 165     165 0 912 my ($self, $name, $sql, @args) = @_;
723 165 100       788 my $db = $self->{db} ? $self->{db} : $self;
724 165         264 my $st;
725 165 100       404 if ($name) {
726 127 100 100     2154 if (!($st = ($db->{private_ipc_lite_prep}||{})->{$name})) {
727 54         576 $st = $db->{private_ipc_lite_prep}->{$name} = $db->prepare($sql);
728             }
729             } else {
730 38         378 $st = $db->prepare($sql);
731             }
732 165         67869760 my $ok = $st->execute(@args);
733 165 100 66     5684110 if ($ok && $st->{NUM_OF_FIELDS}) {
734 103         326402 return $st;
735             } else {
736 62         870 return $ok;
737             }
738             }
739              
740             sub END {
741             # no refs to statement handles
742 8     8   7812 for my $tid_dbs (values(%DBS)) {
743 9         23 for (values(%{$tid_dbs})) {
  9         51  
744 9         1653 $_->{private_ipc_lite_prep} = undef;
745             }
746             }
747             }
748              
749             sub defaultpath {
750 11     11 0 16 my ($self, $callpack) = @_;
751              
752 11 100       35 if (!$DEFAULT_PATH{$callpack}) {
753 1         6 require Cwd;
754 1         70 my $prog = Cwd::abs_path($0);
755             #my $prog = $0;
756             #require File::Spec;
757             #$prog = (File::Spec->splitpath($prog))[2];
758 1         3 $DEFAULT_PATH{$callpack} = nametopath($prog);
759             }
760 11         32 return $DEFAULT_PATH{$callpack};
761             }
762              
763             sub nametopath {
764 1     1 0 2 my ($name) = @_;
765 1         7 $name =~ s/[\/\\\:\!\&\*]/_/g;
766 1         5 require File::Spec;
767 1         102 my $tmp = File::Spec->tmpdir;
768 1         16 $tmp = File::Spec->catfile($tmp, "$name.ipclitedb");
769 1         6 return $tmp;
770             }
771              
772              
773             sub fatalerror
774             {
775 0     0 0 0 $SIG{__DIE__} = undef;
776 0         0 require Carp;
777 0         0 Carp::confess();
778             }
779              
780             sub checkdb {
781 162     162 0 410 my $self = shift;
782 162         493 my $tid = threadid();
783 162 100       1025 if ($tid != $self->{tid}) {
784 3         57 $self->open_pathdb();
785             }
786             }
787              
788             sub threadid {
789 185     185 0 422 my $tid = 0;
790              
791             # todo add more methods
792            
793 185         508 $tid = eval {
794 185         5118881 require threads;
795 0         0 threads->self->tid();
796             };
797              
798 185 50 33     52435 if (!$tid && $^O =~ /win32/i) {
799 0         0 $tid = eval {
800 0         0 require Win32;
801 0         0 Win32::GetCurrentThreadId();
802             };
803             }
804              
805 185 50       928 if (!$tid) {
806             #this fixes forking issues on older perls
807 185         596 $tid = $$;
808             }
809            
810 185         577 return $tid;
811             }
812              
813             sub hereiam {
814 0     0 0   my ($package, $filename, $line, $subroutine) = caller(1);
815 0           print "$package $line: $subroutine (";
816 0           ($package, $filename, $line, $subroutine) = caller(2);
817 0           print "$package $line: $subroutine)\n";
818             }
819              
820             1;
821              
822             __END__