File Coverage

examples/testsimplecdb.pl
Criterion Covered Total %
statement 103 109 94.5
branch 32 46 69.5
condition 4 6 66.6
subroutine 7 8 87.5
pod n/a
total 146 169 86.3


line stmt bran cond sub pod time code
1             #!/usr/local/bin/perl -w
2              
3 7     7   37 use strict;
  7         7  
  7         235  
4              
5 7     7   4124 use SimpleCDB; # exports as per Fcntl
  7         16  
  7         40868  
6              
7             # test the SimpleCDB
8             # - create a DB, then fork off a number of readers
9             # - every so often recreate the DB
10              
11 7   50     41 my $records = shift || 1_000;
12              
13 7   100     44 my $readers = shift || 0;
14              
15 7 100       14 my $cleanup = shift; $cleanup = 1 unless defined $cleanup;
  7         27  
16              
17 7 100       922 warn "$records records, $readers readers, ". ($cleanup ? '' : 'not ') .
18             "cleaning up afterwards\n";
19              
20 7   50     83 my $columns = ($ENV{COLUMNS} || 80) - 8;
21 7         28 $| = 1;
22              
23 7         37 $SimpleCDB::DEBUG = $ENV{SIMPLECDBDEBUG};
24              
25             # range of key,value chars
26             #my @d = map {chr($_)} 0x20..0x7e;
27 7         35 my @d = map {chr($_)} 0x00..0xff;
  1792         5274  
28 7         81 my $magic = pop @d; # will be inserted in every value
29              
30             sub update
31             {
32             # create
33 10     10   414 print "update: ";
34 10         27 my %h;
35 10 50       165 tie %h, 'SimpleCDB', 'db', O_WRONLY|O_TRUNC
36             or die "tie failed: $SimpleCDB::ERROR\n";
37              
38 10         38 my $n = $records/$columns;
39 10         25 my $m = 1;
40 10         14 my $i;
41 10         46 for ($i = 0; $i < $records; $i++)
42             {
43 181000         302246 my $j = $i % @d;
44 181000         225589 my $k = $i;
45 181000         5301202 my $v = join '', (@d[$j..$#d], @d[0..($j-1)])[0..rand(@d)];
46 181000         2172128 substr($v, rand(length($v)), 1) = $magic;
47 181000         888791 $h{$k} = $v;
48 181000 50       1560217 die "store: $SimpleCDB::ERROR" if $SimpleCDB::ERROR;
49 181000 100       673209 $m += $n, print '.' if ($i == int $m);
50             }
51              
52 10         234 untie %h; # release DB
53 10         562 print "\n";
54             }
55              
56             sub qgrep
57             # check the number of records
58             {
59 7     7   14 my %h;
60 7         129 print 'grep: ';
61 7 50       83 tie %h, 'SimpleCDB', 'db', O_RDONLY, 0
62             or die "tie failed: $SimpleCDB::ERROR\n";
63              
64 7         21 my $n = $records/$columns;
65 7         14 my $m = 1;
66 7         20 my $i = 0;
67 7         82 while (my ($k, $v) = each %h)
68             {
69 121000 50       456730 die "invalid record\n" unless $v =~ /$magic/;
70 121000 100       641501 $m += $n, print '+' if ($i++ == int $m);
71             }
72 7 50       59 die "invalid number of records: expected $records, got $i\n"
73             if ($i != $records);
74 7         442 print "\n";
75              
76 7         83 untie %h;
77             }
78              
79             sub query
80             {
81 121     121   699 my %h;
82 121         18664 print 'o'; # "open"
83 121 50       3429 unless (tie %h, 'SimpleCDB', 'db', O_RDONLY)
84             {
85 0 0       0 if ($! == POSIX::EWOULDBLOCK)
86             {
87 0         0 print "!";
88             }
89             else
90             {
91 0         0 die "tie failed: $SimpleCDB::ERROR\n";
92             }
93 0         0 return undef;
94             }
95              
96             #print "$$ query:\n";
97              
98 121         211 while (1)
99             {
100 642         3888 my $i = int rand($records);
101 642         9016 my $v = $h{$i};
102 641 50       3988 die "fetch: $SimpleCDB::ERROR" if $SimpleCDB::ERROR;
103             #print "$$\t$i = " . (defined $v ? 'ok' : '-') . "\n";
104 641         56808 print '+';
105 641 50       4305 die "there's just no magic between us anymore... [$v]\n"
106             unless $v =~ /$magic/;
107 641 100       4081 last if rand() > 0.8;
108             }
109 120         4063 print "\n";
110              
111 120         1723 untie %h;
112             }
113              
114 7         35 update();
115              
116 7         41 qgrep();
117              
118 7         27 my @kids;
119             my $i;
120 7 100       234 print "starting readers\n" if $readers;
121 7         48 for ($i = 0; $i < $readers; $i++)
122             {
123 20         43957 my $p = fork;
124 20         1596 srand();
125 20 100       533 unless ($p) { @kids = (); last }
  5         750  
  5         194  
126 15         834 push (@kids, $p);
127             }
128              
129 7 100       480 if ($readers)
130             {
131 6 100       386 if (@kids) # parent
132             {
133             # an exercise in catching children
134             # - perl 5.00x's signal handling is not reliable, and I quote from
135             # perlipc "... doing nearly anything in your handler could in
136             # theory trigger a memory fault". Nice, hey?
137             # - hashes are probably not reliable, given that presumably memory
138             # allocation can occur at any time. Hopefully a presized array is
139             # ok...
140             # - apparently 5.6 has signals handled via a separate thread, yippee
141 1         52 my @zombies = map { 0 } @kids;
  5         45  
142 1         10 my $z = 0;
143             eval
144 1         15 {
145 1     1   151 local $SIG{INT} = sub { die "SIGINT\n" };
  1         74  
146 1         35 local $SIG{TERM} = $SIG{INT};
147 1     0   134 local $SIG{CHLD} = sub { $zombies[$z++] = wait; die "SIGCHLD\n" };
  0         0  
  0         0  
148              
149 1         3 while (1)
150             {
151 4         106227244 select(undef, undef, undef, 30);
152 4         128 update();
153             }
154             };
155 1 50       47 warn "\nchild exited unexpectedly\n" if $@ =~ /SIGCHLD/;
156 1         17 print "\nstopping readers\n";
157             # who's left?
158             # - could just signal all @kids, but some may have exited already
159             # and thus a race condition arises - don't want to signal another
160             # unrelated process by accident (yes, yes, the probability of this
161             # happening is approximately zero, but someday I might want to do
162             # this for real so I can come back to this code and see how I did
163             # it. Ok? :-)
164             # find complement of @kids U @zombies
165 1         6 my %k = map { $_, 1 } @kids;
  5         27  
166 1 50       4 map { delete $k{$_} if $_ } @zombies;
  5         18  
167 1         79 kill INT => keys %k;
168 1         9 while (%k) { my $pid = wait; delete $k{$pid} }
  5         1285667  
  5         71  
169 1 50       17 die "\n" if $@ =~ /SIGCHLD/;
170             }
171             else # child
172             {
173             eval
174 5         193 {
175 5     5   1362 local $SIG{INT} = sub { die "SIGINT\n" };
  5         310  
176 5         270 local $SIG{TERM} = $SIG{INT};
177 5         41 while (1)
178             {
179 125         539770548 select(undef, undef, undef, 2 + rand(5));
180 125         1616 query();
181             }
182             };
183 5         8 exit;
184             }
185             }
186              
187 2 100       7 if ($cleanup)
188             {
189 1         22 $ENV{PATH} = '/bin:/usr/bin';
190 1 50       0 system(qw/rm -rf/, 'db') == 0 or die "erk: couldn't clean up\n";
191             }