| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
2
|
|
|
|
|
|
|
package FlatFile::DataStore::DBM; |
|
3
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
FlatFile::DataStore::DBM - Perl module that implements a flatfile |
|
8
|
|
|
|
|
|
|
datastore with a DBM file key access. |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=head1 SYNOPSYS |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use Fctnl; |
|
13
|
|
|
|
|
|
|
use FlatFile::DataStore::DBM; |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
$FlatFile::DataStore::DBM::dbm_package = "SDBM_File"; # the defaults |
|
16
|
|
|
|
|
|
|
$FlatFile::DataStore::DBM::dbm_parms = [ O_CREAT|O_RDWR, 0666 ]; |
|
17
|
|
|
|
|
|
|
$FlatFile::DataStore::DBM::dbm_lock_ext = ".dir"; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# new object |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my $obj = tie my %dshash, 'FlatFile::DataStore::DBM', { |
|
22
|
|
|
|
|
|
|
name => "dsname", |
|
23
|
|
|
|
|
|
|
dir => "/my/datastore/directory", |
|
24
|
|
|
|
|
|
|
}; |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# create a record and retrieve it |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $id = "testrec1"; |
|
29
|
|
|
|
|
|
|
my $record = $dshash{ $id } = { data => "Test record", user => "Test user data" }; |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# update it |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
$record->data( "Updating the test record." ); |
|
34
|
|
|
|
|
|
|
$dshash{ $id } = $record; |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# delete it |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
delete $dshash{ $id }; |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# get its history |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my @records = $obj->history( $id ); |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
FlatFile::DataStore::DBM implements a tied hash interface to a |
|
47
|
|
|
|
|
|
|
flatfile datastore. The hash keys are strings that you provide. |
|
48
|
|
|
|
|
|
|
These keys do not necessarily have to exist as data in the record. |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
In the case of delete, you're limited in the tied interface -- you |
|
51
|
|
|
|
|
|
|
can't supply a "delete record" (one that has information about the |
|
52
|
|
|
|
|
|
|
delete operation). Instead, it will simply retrieve the existing |
|
53
|
|
|
|
|
|
|
record and store that as the delete record. |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
Record data may be created or updated (i.e., STORE'd) three ways: |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
As a data string (or scalar reference), e.g., |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
$record = $dshash{ $id } = $record_data; |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
As a hash reference, e.g. |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
$record = $dshash{ $id } = { data => $record_data, user => $user_data }; |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
As a record object (record data and user data gotten from object), |
|
66
|
|
|
|
|
|
|
e.g., |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
$record->data( $record_data ); |
|
69
|
|
|
|
|
|
|
$record->user( $user_data ); |
|
70
|
|
|
|
|
|
|
$record = $dshash{ $id } = $record; |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
In the last line above, the object fetched is not the same as |
|
73
|
|
|
|
|
|
|
the one given to be stored (it has a different preamble). |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
FWIW, this module is not a subclass of FlatFile::DataStore. Instead, |
|
76
|
|
|
|
|
|
|
it is a wrapper, so it's a "has a" relationship rather than an "is a" |
|
77
|
|
|
|
|
|
|
one. But many of the public flatfile methods are available via the |
|
78
|
|
|
|
|
|
|
tied object, as illustrated by the history() call in the synopsis. |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
These methods include |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
name |
|
83
|
|
|
|
|
|
|
dir |
|
84
|
|
|
|
|
|
|
retrieve |
|
85
|
|
|
|
|
|
|
retrieve_preamble |
|
86
|
|
|
|
|
|
|
locate_record_data |
|
87
|
|
|
|
|
|
|
history |
|
88
|
|
|
|
|
|
|
userdata |
|
89
|
|
|
|
|
|
|
howmany |
|
90
|
|
|
|
|
|
|
lastkeynum |
|
91
|
|
|
|
|
|
|
nextkeynum |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
Note that create(), update(), and delete() are not included in this |
|
94
|
|
|
|
|
|
|
list. If a datastore is set up using this module, all updates to its |
|
95
|
|
|
|
|
|
|
data should use this module. This will keep the keys in sync with |
|
96
|
|
|
|
|
|
|
the data. |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=head1 VERSION |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
FlatFile::DataStore::DBM version 1.03 |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=cut |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
our $VERSION = '1.03'; |
|
105
|
|
|
|
|
|
|
|
|
106
|
2
|
|
|
2
|
|
109727
|
use 5.008003; |
|
|
2
|
|
|
|
|
10
|
|
|
|
2
|
|
|
|
|
114
|
|
|
107
|
2
|
|
|
2
|
|
12
|
use strict; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
89
|
|
|
108
|
2
|
|
|
2
|
|
12
|
use warnings; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
107
|
|
|
109
|
|
|
|
|
|
|
|
|
110
|
2
|
|
|
2
|
|
12
|
use Fcntl qw(:DEFAULT :flock); |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
1186
|
|
|
111
|
2
|
|
|
2
|
|
14
|
use Carp; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
127
|
|
|
112
|
|
|
|
|
|
|
|
|
113
|
2
|
|
|
2
|
|
2259
|
use FlatFile::DataStore; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
6952
|
|
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
118
|
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head2 Tieing the hash |
|
120
|
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Accepts hash ref giving values for C and C. |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
tie my %dshash, 'FlatFile::DataStore::DBM', { |
|
124
|
|
|
|
|
|
|
name => $name, |
|
125
|
|
|
|
|
|
|
dir => $dir, |
|
126
|
|
|
|
|
|
|
}; |
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
To initialize a new datastore, pass the URI as the value of the |
|
129
|
|
|
|
|
|
|
C parameter, e.g., |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
tie my %dshash, 'FlatFile::DataStore::DBM', { |
|
132
|
|
|
|
|
|
|
dir => $dir, |
|
133
|
|
|
|
|
|
|
name => $name, |
|
134
|
|
|
|
|
|
|
uri => join( ";" => |
|
135
|
|
|
|
|
|
|
"http://example.com?name=$name", |
|
136
|
|
|
|
|
|
|
"desc=My%20Data%20Store", |
|
137
|
|
|
|
|
|
|
"defaults=medium", |
|
138
|
|
|
|
|
|
|
"user=8-%20-%7E", |
|
139
|
|
|
|
|
|
|
"recsep=%0A", |
|
140
|
|
|
|
|
|
|
), |
|
141
|
|
|
|
|
|
|
}; |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
(See URI Configuration in FlatFile::DataStore.) |
|
144
|
|
|
|
|
|
|
Also accepts a C parameter, which sets the default user |
|
145
|
|
|
|
|
|
|
data for this instance. |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
Returns a reference to the FlatFile::DataStore::DBM object. |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=head2 Object Methods |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head3 get_key( $keynum ); |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
Gets the key associated with a record sequence number (keynum). |
|
156
|
|
|
|
|
|
|
This could be handy if you have a record, but don't have its key |
|
157
|
|
|
|
|
|
|
in the DBM file, e.g., |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# have a record to update, but forgot its key |
|
160
|
|
|
|
|
|
|
# (the key isn't necessarily in the record) |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
my $id = tied(%dshash)->get_key( $record->keynum ); |
|
163
|
|
|
|
|
|
|
$dshash{ $id } = $record; |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=cut |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub get_key { |
|
168
|
2
|
|
|
2
|
1
|
1274
|
my( $self, $keynum ) = @_; |
|
169
|
|
|
|
|
|
|
|
|
170
|
2
|
100
|
66
|
|
|
213
|
croak qq/Not a keynum: $keynum/ |
|
171
|
|
|
|
|
|
|
unless defined $keynum and $keynum =~ /^[0-9]+$/; |
|
172
|
|
|
|
|
|
|
|
|
173
|
1
|
|
|
|
|
5
|
my $ds = $self->datastore; |
|
174
|
1
|
|
|
|
|
5
|
my $dir = $ds->dir; |
|
175
|
1
|
|
|
|
|
6
|
my $name = $ds->name; |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# lock the dbm file and read the key |
|
178
|
1
|
|
|
|
|
4
|
$self->readlock; |
|
179
|
1
|
50
|
|
|
|
4
|
tie my %dbm_hash, $self->dbm_package, "$dir/$name", @{$self->dbm_parms} |
|
|
1
|
|
|
|
|
8
|
|
|
180
|
|
|
|
|
|
|
or die "Can't tie dbm hash: $!"; |
|
181
|
|
|
|
|
|
|
|
|
182
|
1
|
|
|
|
|
18
|
my $key = $dbm_hash{ "_$keynum" }; |
|
183
|
|
|
|
|
|
|
|
|
184
|
1
|
|
|
|
|
21
|
untie %dbm_hash; |
|
185
|
1
|
|
|
|
|
4
|
$self->unlock; |
|
186
|
|
|
|
|
|
|
|
|
187
|
1
|
|
|
|
|
4
|
$key; # returned |
|
188
|
|
|
|
|
|
|
} |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head3 get_keynum( $key ); |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
Gets the record sequence number (keynum) associated with a key. Don't |
|
195
|
|
|
|
|
|
|
have a good use case yet -- included this method as a complement to |
|
196
|
|
|
|
|
|
|
get_key(). |
|
197
|
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=cut |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub get_keynum { |
|
201
|
2
|
|
|
2
|
1
|
18
|
my( $self, $key ) = @_; |
|
202
|
|
|
|
|
|
|
|
|
203
|
2
|
100
|
|
|
|
187
|
croak qq/Unsupported key format: $key/ if $key =~ /^_[0-9]+$/; |
|
204
|
|
|
|
|
|
|
|
|
205
|
1
|
|
|
|
|
3
|
my $ds = $self->datastore; |
|
206
|
1
|
|
|
|
|
4
|
my $dir = $ds->dir; |
|
207
|
1
|
|
|
|
|
3
|
my $name = $ds->name; |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# lock the dbm file and read the keynum |
|
210
|
1
|
|
|
|
|
4
|
$self->readlock; |
|
211
|
1
|
50
|
|
|
|
4
|
tie my %dbm_hash, $self->dbm_package, "$dir/$name", @{$self->dbm_parms} |
|
|
1
|
|
|
|
|
3
|
|
|
212
|
|
|
|
|
|
|
or die "Can't tie dbm hash: $!"; |
|
213
|
|
|
|
|
|
|
|
|
214
|
1
|
|
|
|
|
13
|
my $keynum = $dbm_hash{ $key }; |
|
215
|
|
|
|
|
|
|
|
|
216
|
1
|
|
|
|
|
16
|
untie %dbm_hash; |
|
217
|
1
|
|
|
|
|
3
|
$self->unlock; |
|
218
|
|
|
|
|
|
|
|
|
219
|
1
|
|
|
|
|
4
|
$keynum; # returned |
|
220
|
|
|
|
|
|
|
} |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
223
|
|
|
|
|
|
|
# accessors |
|
224
|
|
|
|
|
|
|
# the following are required attributes, so simple accessors are okay |
|
225
|
|
|
|
|
|
|
# |
|
226
|
|
|
|
|
|
|
# Private methods. |
|
227
|
|
|
|
|
|
|
|
|
228
|
49
|
50
|
|
49
|
0
|
148
|
sub datastore {for($_[0]->{datastore }){$_=$_[1]if@_>1;return$_}} |
|
|
49
|
|
|
|
|
129
|
|
|
|
49
|
|
|
|
|
140
|
|
|
229
|
74
|
100
|
|
74
|
0
|
185
|
sub locked {for($_[0]->{locked }){$_=$_[1]if@_>1;return$_}} |
|
|
74
|
|
|
|
|
195
|
|
|
|
74
|
|
|
|
|
178
|
|
|
230
|
74
|
50
|
|
74
|
0
|
220
|
sub dbm_lock_file {for($_[0]->{dbm_lock_file}){$_=$_[1]if@_>1;return$_}} |
|
|
74
|
|
|
|
|
160
|
|
|
|
74
|
|
|
|
|
154
|
|
|
231
|
37
|
50
|
|
37
|
0
|
88
|
sub dbm_package {for($_[0]->{dbm_package }){$_=$_[1]if@_>1;return$_}} |
|
|
37
|
|
|
|
|
98
|
|
|
|
37
|
|
|
|
|
128
|
|
|
232
|
37
|
50
|
|
37
|
0
|
94
|
sub dbm_parms {for($_[0]->{dbm_parms }){$_=$_[1]if@_>1;return$_}} |
|
|
37
|
|
|
|
|
85
|
|
|
|
37
|
|
|
|
|
1954
|
|
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
235
|
|
|
|
|
|
|
# globals |
|
236
|
|
|
|
|
|
|
# |
|
237
|
|
|
|
|
|
|
# These are read in TIEHASH(). They may be changed prior to calling |
|
238
|
|
|
|
|
|
|
# tie(), e.g., |
|
239
|
|
|
|
|
|
|
# |
|
240
|
|
|
|
|
|
|
# my $ds_parms = { name => $ds_name, dir => $ds_dir }; |
|
241
|
|
|
|
|
|
|
# $FlatFile::DataStore::DBM::dbm_parms = [ O_RDONLY, 0666 ]; |
|
242
|
|
|
|
|
|
|
# |
|
243
|
|
|
|
|
|
|
# tie my %hash, "FlatFile::DataStore::DBM", $ds_parms; |
|
244
|
|
|
|
|
|
|
# |
|
245
|
|
|
|
|
|
|
# ... or different values may be passed to tie() using a hash |
|
246
|
|
|
|
|
|
|
# reference as the second parameter, e.g., |
|
247
|
|
|
|
|
|
|
# |
|
248
|
|
|
|
|
|
|
# my $ds_parms = { name => $ds_name, dir => $ds_dir }; |
|
249
|
|
|
|
|
|
|
# my $dbm_specs = { dbm_parms => [ O_RDONLY, 0666 ] } |
|
250
|
|
|
|
|
|
|
# |
|
251
|
|
|
|
|
|
|
# tie my %hash, "FlatFile::DataStore::DBM", $ds_parms, $dbm_specs; |
|
252
|
|
|
|
|
|
|
# |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
our $dbm_package = "SDBM_File"; |
|
255
|
|
|
|
|
|
|
our $dbm_parms = [ O_CREAT|O_RDWR, 0666 ]; |
|
256
|
|
|
|
|
|
|
our $dbm_lock_ext = ".dir"; |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
259
|
|
|
|
|
|
|
# TIEHASH() supports tied hash access |
|
260
|
|
|
|
|
|
|
# |
|
261
|
|
|
|
|
|
|
# Coding note: in TIEHASH(), the object attributes are set directly in |
|
262
|
|
|
|
|
|
|
# the hash. In all the other subs the above accessors are used. |
|
263
|
|
|
|
|
|
|
# |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
sub TIEHASH { |
|
266
|
9
|
|
|
9
|
|
10868
|
my( $class, $ds_parms, $dbm_specs ) = @_; |
|
267
|
|
|
|
|
|
|
|
|
268
|
9
|
|
|
|
|
75
|
my $ds = FlatFile::DataStore->new( $ds_parms ); |
|
269
|
8
|
|
|
|
|
26
|
my $dir = $ds->dir; |
|
270
|
8
|
|
|
|
|
28
|
my $name = $ds->name; |
|
271
|
|
|
|
|
|
|
|
|
272
|
8
|
|
|
|
|
61
|
my $self = { |
|
273
|
|
|
|
|
|
|
datastore => $ds, |
|
274
|
|
|
|
|
|
|
dbm_package => $dbm_package, # may be changed by dbm_specs |
|
275
|
|
|
|
|
|
|
dbm_parms => $dbm_parms, # " |
|
276
|
|
|
|
|
|
|
dbm_lock_ext => $dbm_lock_ext, # " |
|
277
|
|
|
|
|
|
|
}; |
|
278
|
8
|
50
|
|
|
|
29
|
if( $dbm_specs ) { |
|
279
|
0
|
|
|
|
|
0
|
$self->{ $_ } = $dbm_specs->{ $_ } for keys %$dbm_specs; |
|
280
|
|
|
|
|
|
|
} |
|
281
|
8
|
|
|
|
|
40
|
$self->{'dbm_lock_file'} = "$dir/$name$self->{'dbm_lock_ext'}"; |
|
282
|
|
|
|
|
|
|
|
|
283
|
8
|
50
|
|
|
|
832
|
eval qq{require $self->{'dbm_package'}; 1} |
|
284
|
|
|
|
|
|
|
or croak qq/Can't use $self->{'dbm_package'}: $@/; |
|
285
|
|
|
|
|
|
|
|
|
286
|
8
|
|
|
|
|
81
|
bless $self, $class; |
|
287
|
|
|
|
|
|
|
} |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
290
|
|
|
|
|
|
|
# FETCH() supports tied hash access |
|
291
|
|
|
|
|
|
|
# Returns a FlatFile::DataStore::Record object. |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub FETCH { |
|
294
|
17
|
|
|
17
|
|
108
|
my( $self, $key ) = @_; |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# block efforts to fetch a "_keynum" entry |
|
297
|
17
|
100
|
|
|
|
262
|
croak qq/Unsupported key format: $key/ if $key =~ /^_[0-9]+$/; |
|
298
|
|
|
|
|
|
|
|
|
299
|
16
|
|
|
|
|
51
|
my $ds = $self->datastore; |
|
300
|
16
|
|
|
|
|
57
|
my $dir = $ds->dir; |
|
301
|
16
|
|
|
|
|
53
|
my $name = $ds->name; |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# lock the dbm file and read the keynum |
|
304
|
16
|
|
|
|
|
55
|
$self->readlock; |
|
305
|
16
|
50
|
|
|
|
54
|
tie my %dbm_hash, $self->dbm_package, "$dir/$name", @{$self->dbm_parms} |
|
|
16
|
|
|
|
|
48
|
|
|
306
|
|
|
|
|
|
|
or die "Can't tie dbm hash: $!"; |
|
307
|
|
|
|
|
|
|
|
|
308
|
16
|
|
|
|
|
235
|
my $keynum = $dbm_hash{ $key }; |
|
309
|
|
|
|
|
|
|
|
|
310
|
16
|
|
|
|
|
288
|
untie %dbm_hash; |
|
311
|
16
|
|
|
|
|
45
|
$self->unlock; |
|
312
|
|
|
|
|
|
|
|
|
313
|
16
|
50
|
|
|
|
40
|
return unless defined $keynum; |
|
314
|
16
|
|
|
|
|
74
|
$ds->retrieve( $keynum ); # retrieve and return record |
|
315
|
|
|
|
|
|
|
} |
|
316
|
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
318
|
|
|
|
|
|
|
# STORE() supports tied hash access |
|
319
|
|
|
|
|
|
|
# Returns a FlatFile::DataStore::Record object. |
|
320
|
|
|
|
|
|
|
# |
|
321
|
|
|
|
|
|
|
# to help with FIRSTKEY/NEXTKEY, we're keeping two entries |
|
322
|
|
|
|
|
|
|
# in the dbm file for every record: |
|
323
|
|
|
|
|
|
|
# 1. record id => key sequence number |
|
324
|
|
|
|
|
|
|
# 2. key sequence number => record id |
|
325
|
|
|
|
|
|
|
# |
|
326
|
|
|
|
|
|
|
# to avoid collisions with numeric keys, the key of the second |
|
327
|
|
|
|
|
|
|
# entry has an underscore pasted on to the front, e.g., a record |
|
328
|
|
|
|
|
|
|
# whose id is "able_baker_charlie" and whose keynum is 257 would |
|
329
|
|
|
|
|
|
|
# have these entries: |
|
330
|
|
|
|
|
|
|
# 1. able_baker_charlie => 257 |
|
331
|
|
|
|
|
|
|
# 2. _257 => able_baker_charlie |
|
332
|
|
|
|
|
|
|
# |
|
333
|
|
|
|
|
|
|
# Note: the $error variable is intended to avoid having a croak |
|
334
|
|
|
|
|
|
|
# between writelock() and unlock(). On linux systems that don't |
|
335
|
|
|
|
|
|
|
# allow a process to have multiple locks on the same file, if you |
|
336
|
|
|
|
|
|
|
# trap those croaks in an eval{} (like for testing), the program |
|
337
|
|
|
|
|
|
|
# will hang waiting for a lock. |
|
338
|
|
|
|
|
|
|
# |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
sub STORE { |
|
341
|
18
|
|
|
18
|
|
3167
|
my( $self, $key, $parms ) = @_; |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# block efforts to store to "_keynum" entries |
|
344
|
18
|
100
|
|
|
|
230
|
croak qq/Unsupported key format: $key/ if $key =~ /^_[0-9]+$/; |
|
345
|
|
|
|
|
|
|
|
|
346
|
17
|
|
|
|
|
61
|
my $ds = $self->datastore; |
|
347
|
17
|
|
|
|
|
60
|
my $dir = $ds->dir; |
|
348
|
17
|
|
|
|
|
59
|
my $name = $ds->name; |
|
349
|
|
|
|
|
|
|
|
|
350
|
17
|
|
|
|
|
29
|
my $error; |
|
351
|
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# lock the dbm file and read the keynum |
|
353
|
17
|
|
|
|
|
59
|
$self->writelock; |
|
354
|
17
|
50
|
|
|
|
55
|
tie my %dbm_hash, $self->dbm_package, "$dir/$name", @{$self->dbm_parms} |
|
|
17
|
|
|
|
|
50
|
|
|
355
|
|
|
|
|
|
|
or die "Can't tie dbm hash: $!"; |
|
356
|
|
|
|
|
|
|
|
|
357
|
17
|
|
|
|
|
294
|
my $keynum = $dbm_hash{ $key }; |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# $parms may be record, href, sref, or string |
|
360
|
17
|
|
|
|
|
53
|
my $reftype = ref $parms; |
|
361
|
|
|
|
|
|
|
|
|
362
|
17
|
|
|
|
|
33
|
my $record; # to be returned |
|
363
|
|
|
|
|
|
|
|
|
364
|
17
|
100
|
|
|
|
49
|
if( defined $keynum ) { # update |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# record data string |
|
367
|
4
|
50
|
33
|
|
|
46
|
if( !$reftype or $reftype eq "SCALAR" ) { |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
368
|
0
|
|
|
|
|
0
|
$record = $ds->retrieve( $keynum ); # read it |
|
369
|
0
|
|
|
|
|
0
|
$record->data( $parms ); # update it |
|
370
|
0
|
|
|
|
|
0
|
$record = $ds->update( $record ); # write it |
|
371
|
|
|
|
|
|
|
} |
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
# record object |
|
374
|
|
|
|
|
|
|
elsif( $reftype =~ /Record/ ) { |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
# trying to update a record using the wrong key? |
|
377
|
2
|
100
|
|
|
|
11
|
if( $keynum != $parms->keynum ) { |
|
378
|
1
|
|
|
|
|
3
|
$error = qq/Record key number doesn't match key/; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
else { |
|
381
|
1
|
|
|
|
|
6
|
$record = $ds->update( $parms ); |
|
382
|
|
|
|
|
|
|
} |
|
383
|
|
|
|
|
|
|
} |
|
384
|
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
# hash, e.g., {data=>'record data',user=>'user data'} |
|
386
|
|
|
|
|
|
|
elsif( $reftype eq 'HASH' ) { |
|
387
|
1
|
50
|
|
|
|
9
|
$parms->{'record'} = $ds->retrieve( $keynum ) unless $parms->{'record'}; |
|
388
|
1
|
|
|
|
|
7
|
$record = $ds->update( $parms ); |
|
389
|
|
|
|
|
|
|
} |
|
390
|
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
else { |
|
392
|
1
|
|
|
|
|
4
|
$error = qq/Unsupported ref type: $reftype/; |
|
393
|
|
|
|
|
|
|
} |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
} |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
else { # create |
|
398
|
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
# record data string |
|
400
|
13
|
100
|
66
|
|
|
137
|
if( !$reftype or $reftype eq "SCALAR" ) { |
|
|
|
100
|
100
|
|
|
|
|
|
401
|
1
|
|
|
|
|
7
|
$record = $ds->create({ data => $parms }); |
|
402
|
|
|
|
|
|
|
} |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# record object or hash, e.g., |
|
405
|
|
|
|
|
|
|
# { data => 'record data', user => 'user data' } |
|
406
|
|
|
|
|
|
|
elsif( $reftype =~ /Record/ or |
|
407
|
|
|
|
|
|
|
$reftype eq 'HASH' ) { |
|
408
|
11
|
|
|
|
|
61
|
$record = $ds->create( $parms ); |
|
409
|
|
|
|
|
|
|
} |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
else { |
|
412
|
1
|
|
|
|
|
4
|
$error = qq/Unsupported ref type: $reftype/; |
|
413
|
|
|
|
|
|
|
} |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# create succeeded, let's store the key |
|
416
|
13
|
100
|
|
|
|
40
|
unless( $error ) { |
|
417
|
12
|
|
|
|
|
54
|
for( $record->keynum ) { |
|
418
|
12
|
|
|
|
|
383
|
$dbm_hash{ $key } = $_; |
|
419
|
12
|
|
|
|
|
208
|
$dbm_hash{ "_$_" } = $key; |
|
420
|
|
|
|
|
|
|
} |
|
421
|
|
|
|
|
|
|
} |
|
422
|
|
|
|
|
|
|
} |
|
423
|
|
|
|
|
|
|
|
|
424
|
17
|
|
|
|
|
354
|
untie %dbm_hash; |
|
425
|
17
|
|
|
|
|
67
|
$self->unlock; |
|
426
|
|
|
|
|
|
|
|
|
427
|
17
|
100
|
|
|
|
451
|
croak $error if $error; |
|
428
|
|
|
|
|
|
|
|
|
429
|
14
|
|
|
|
|
149
|
$record; # returned |
|
430
|
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
} |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
434
|
|
|
|
|
|
|
# DELETE() supports tied hash access |
|
435
|
|
|
|
|
|
|
# Returns a FlatFile::DataStore::Record object. |
|
436
|
|
|
|
|
|
|
# |
|
437
|
|
|
|
|
|
|
# Otherwise, we must have a record to delete one, so we retrieve |
|
438
|
|
|
|
|
|
|
# it first. |
|
439
|
|
|
|
|
|
|
# |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub DELETE { |
|
442
|
1
|
|
|
1
|
|
3
|
my( $self, $key ) = @_; |
|
443
|
|
|
|
|
|
|
|
|
444
|
1
|
|
|
|
|
6
|
my $ds = $self->datastore; |
|
445
|
1
|
|
|
|
|
6
|
my $dir = $ds->dir; |
|
446
|
1
|
|
|
|
|
4
|
my $name = $ds->name; |
|
447
|
|
|
|
|
|
|
|
|
448
|
1
|
|
|
|
|
5
|
$self->writelock; |
|
449
|
1
|
50
|
|
|
|
5
|
tie my %dbm_hash, $self->dbm_package, "$dir/$name", @{$self->dbm_parms} |
|
|
1
|
|
|
|
|
5
|
|
|
450
|
|
|
|
|
|
|
or die "Can't tie dbm hash: $!"; |
|
451
|
|
|
|
|
|
|
|
|
452
|
1
|
|
|
|
|
3
|
my $exists; |
|
453
|
|
|
|
|
|
|
my $record; |
|
454
|
|
|
|
|
|
|
|
|
455
|
1
|
50
|
|
|
|
20
|
if( $exists = exists $dbm_hash{ $key } ) { |
|
456
|
|
|
|
|
|
|
|
|
457
|
1
|
|
|
|
|
7
|
my $keynum = $dbm_hash{ $key }; |
|
458
|
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
# must have a record to delete it |
|
460
|
1
|
|
|
|
|
8
|
$record = $ds->retrieve( $keynum ); |
|
461
|
1
|
|
|
|
|
8
|
$record = $ds->delete( $record ); |
|
462
|
|
|
|
|
|
|
|
|
463
|
1
|
|
|
|
|
31
|
delete $dbm_hash{ $key }; |
|
464
|
1
|
|
|
|
|
16
|
delete $dbm_hash{ "_$keynum" }; |
|
465
|
|
|
|
|
|
|
} |
|
466
|
|
|
|
|
|
|
|
|
467
|
1
|
|
|
|
|
23
|
untie %dbm_hash; |
|
468
|
1
|
|
|
|
|
6
|
$self->unlock; |
|
469
|
|
|
|
|
|
|
|
|
470
|
1
|
50
|
|
|
|
5
|
return unless $exists; |
|
471
|
1
|
|
|
|
|
8
|
$record; # return the "delete record" |
|
472
|
|
|
|
|
|
|
} |
|
473
|
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
475
|
|
|
|
|
|
|
# CLEAR() supports tied hash access |
|
476
|
|
|
|
|
|
|
# except we don't support CLEAR, because it would be very |
|
477
|
|
|
|
|
|
|
# destructive and it would be a pain to recover from an |
|
478
|
|
|
|
|
|
|
# accidental %h = (); |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
sub CLEAR { |
|
481
|
1
|
|
|
1
|
|
199
|
croak qq/Clearing the entire datastore is not supported/; |
|
482
|
|
|
|
|
|
|
} |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
485
|
|
|
|
|
|
|
# FIRSTKEY() supports tied hash access |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
sub FIRSTKEY { |
|
488
|
0
|
|
|
0
|
|
0
|
my( $self ) = @_; |
|
489
|
|
|
|
|
|
|
|
|
490
|
0
|
|
|
|
|
0
|
my $ds = $self->datastore; |
|
491
|
0
|
|
|
|
|
0
|
my $dir = $ds->dir; |
|
492
|
0
|
|
|
|
|
0
|
my $name = $ds->name; |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
# lock the dbm file and read the first key (stored as '_0') |
|
495
|
0
|
|
|
|
|
0
|
$self->readlock; |
|
496
|
0
|
0
|
|
|
|
0
|
tie my %dbm_hash, $self->dbm_package, "$dir/$name", @{$self->dbm_parms} |
|
|
0
|
|
|
|
|
0
|
|
|
497
|
|
|
|
|
|
|
or die "Can't tie dbm hash: $!"; |
|
498
|
|
|
|
|
|
|
|
|
499
|
0
|
|
|
|
|
0
|
my $firstkey = $dbm_hash{ '_0' }; |
|
500
|
|
|
|
|
|
|
|
|
501
|
0
|
|
|
|
|
0
|
untie %dbm_hash; |
|
502
|
0
|
|
|
|
|
0
|
$self->unlock; |
|
503
|
|
|
|
|
|
|
|
|
504
|
0
|
|
|
|
|
0
|
$firstkey; # returned, might be undef |
|
505
|
|
|
|
|
|
|
} |
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
508
|
|
|
|
|
|
|
# NEXTKEY() supports tied hash access |
|
509
|
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
sub NEXTKEY { |
|
511
|
0
|
|
|
0
|
|
0
|
my( $self, $prevkey ) = @_; |
|
512
|
|
|
|
|
|
|
|
|
513
|
0
|
|
|
|
|
0
|
my $ds = $self->datastore; |
|
514
|
0
|
|
|
|
|
0
|
my $dir = $ds->dir; |
|
515
|
0
|
|
|
|
|
0
|
my $name = $ds->name; |
|
516
|
|
|
|
|
|
|
|
|
517
|
0
|
|
|
|
|
0
|
my $nextkey; |
|
518
|
|
|
|
|
|
|
|
|
519
|
|
|
|
|
|
|
# lock the dbm file and get the prev key's keynum |
|
520
|
0
|
|
|
|
|
0
|
$self->readlock; |
|
521
|
0
|
0
|
|
|
|
0
|
tie my %dbm_hash, $self->dbm_package, "$dir/$name", @{$self->dbm_parms} |
|
|
0
|
|
|
|
|
0
|
|
|
522
|
|
|
|
|
|
|
or die "Can't tie dbm hash: $!"; |
|
523
|
|
|
|
|
|
|
|
|
524
|
0
|
|
|
|
|
0
|
my $keynum = $dbm_hash{ $prevkey }; |
|
525
|
|
|
|
|
|
|
|
|
526
|
0
|
0
|
|
|
|
0
|
if( $keynum++ < $ds->lastkeynum ) { |
|
527
|
0
|
|
|
|
|
0
|
$nextkey = $dbm_hash{ "_$keynum" }; |
|
528
|
|
|
|
|
|
|
} |
|
529
|
|
|
|
|
|
|
|
|
530
|
0
|
|
|
|
|
0
|
untie %dbm_hash; |
|
531
|
0
|
|
|
|
|
0
|
$self->unlock; |
|
532
|
|
|
|
|
|
|
|
|
533
|
0
|
|
|
|
|
0
|
$nextkey; # returned, might be undef |
|
534
|
|
|
|
|
|
|
} |
|
535
|
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
537
|
|
|
|
|
|
|
# SCALAR() supports tied hash access |
|
538
|
|
|
|
|
|
|
# Here we're bypassing the dbm file altogether and simply getting |
|
539
|
|
|
|
|
|
|
# the number of non-deleted records in the datastore. This |
|
540
|
|
|
|
|
|
|
# should be the same as the number of (logical) entries in the |
|
541
|
|
|
|
|
|
|
# dbm hash. |
|
542
|
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
sub SCALAR { |
|
544
|
0
|
|
|
0
|
|
0
|
my $self = shift; |
|
545
|
0
|
|
|
|
|
0
|
$self->datastore->howmany; # create|update (not deletes) |
|
546
|
|
|
|
|
|
|
} |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
549
|
|
|
|
|
|
|
# EXISTS() supports tied hash access |
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
sub EXISTS { |
|
552
|
2
|
|
|
2
|
|
24
|
my( $self, $key ) = @_; |
|
553
|
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
# block efforts to look at a "_keynum" entry |
|
555
|
2
|
100
|
|
|
|
191
|
croak qq/Unsupported key format: $key/ if $key =~ /^_[0-9]+$/; |
|
556
|
|
|
|
|
|
|
|
|
557
|
1
|
|
|
|
|
4
|
my $ds = $self->datastore; |
|
558
|
1
|
50
|
|
|
|
5
|
return unless $ds->exists; |
|
559
|
|
|
|
|
|
|
|
|
560
|
1
|
|
|
|
|
5
|
my $dir = $ds->dir; |
|
561
|
1
|
|
|
|
|
5
|
my $name = $ds->name; |
|
562
|
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
# lock the dbm file and call exists on dbm hash |
|
564
|
1
|
|
|
|
|
5
|
$self->readlock; |
|
565
|
1
|
50
|
|
|
|
4
|
tie my %dbm_hash, $self->dbm_package, "$dir/$name", @{$self->dbm_parms} |
|
|
1
|
|
|
|
|
4
|
|
|
566
|
|
|
|
|
|
|
or die "Can't tie dbm hash: $!"; |
|
567
|
|
|
|
|
|
|
|
|
568
|
1
|
|
|
|
|
13
|
my $exists = exists $dbm_hash{ $key }; |
|
569
|
|
|
|
|
|
|
|
|
570
|
1
|
|
|
|
|
19
|
untie %dbm_hash; |
|
571
|
1
|
|
|
|
|
4
|
$self->unlock; |
|
572
|
|
|
|
|
|
|
|
|
573
|
1
|
50
|
|
|
|
11
|
return unless $exists; |
|
574
|
0
|
|
|
|
|
0
|
$exists; |
|
575
|
|
|
|
|
|
|
} |
|
576
|
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
578
|
|
|
|
|
|
|
# UNTIE() supports tied hash access |
|
579
|
|
|
|
|
|
|
# (see perldoc perltie, The "untie" Gotcha) |
|
580
|
|
|
|
|
|
|
|
|
581
|
|
|
|
|
|
|
sub UNTIE { |
|
582
|
0
|
|
|
0
|
|
0
|
my( $self, $count ) = @_; |
|
583
|
0
|
0
|
|
|
|
0
|
carp "untie attempted while $count inner references still exist" if $count; |
|
584
|
|
|
|
|
|
|
} |
|
585
|
|
|
|
|
|
|
|
|
586
|
0
|
|
|
0
|
|
0
|
sub DESTROY {} # to keep from calling AUTOLOAD |
|
587
|
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
589
|
|
|
|
|
|
|
# readlock() |
|
590
|
|
|
|
|
|
|
# Takes a file name, opens it for input, locks it, and stores the |
|
591
|
|
|
|
|
|
|
# open file handle in the object. This file handle isn't really |
|
592
|
|
|
|
|
|
|
# used except for locking, so it's bit of a "lock token" |
|
593
|
|
|
|
|
|
|
# |
|
594
|
|
|
|
|
|
|
# Private method. |
|
595
|
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
sub readlock { |
|
597
|
19
|
|
|
19
|
0
|
33
|
my( $self ) = @_; |
|
598
|
|
|
|
|
|
|
|
|
599
|
19
|
|
|
|
|
47
|
my $file = $self->dbm_lock_file; |
|
600
|
19
|
|
|
|
|
30
|
my $fh; |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
# open $fh, '<', $file or croak qq/Can't open for read $file: $!/; |
|
603
|
19
|
50
|
|
|
|
707
|
sysopen( $fh, $file, O_RDONLY|O_CREAT ) or croak qq/Can't open for read $file: $!/; |
|
604
|
19
|
50
|
|
|
|
139
|
flock $fh, LOCK_SH or croak qq/Can't lock shared $file: $!/; |
|
605
|
19
|
|
|
|
|
40
|
binmode $fh; |
|
606
|
|
|
|
|
|
|
|
|
607
|
19
|
|
|
|
|
49
|
$self->locked( $fh ); |
|
608
|
|
|
|
|
|
|
} |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
611
|
|
|
|
|
|
|
# writelock() |
|
612
|
|
|
|
|
|
|
# Takes a file name, opens it for read/write, locks it, and |
|
613
|
|
|
|
|
|
|
# stores the open file handle in the object. |
|
614
|
|
|
|
|
|
|
# |
|
615
|
|
|
|
|
|
|
# Private method. |
|
616
|
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
sub writelock { |
|
618
|
18
|
|
|
18
|
0
|
30
|
my( $self ) = @_; |
|
619
|
|
|
|
|
|
|
|
|
620
|
18
|
|
|
|
|
72
|
my $file = $self->dbm_lock_file; |
|
621
|
18
|
|
|
|
|
28
|
my $fh; |
|
622
|
|
|
|
|
|
|
|
|
623
|
18
|
50
|
|
|
|
1092
|
sysopen( $fh, $file, O_RDWR|O_CREAT ) or croak qq/Can't open for read-write $file: $!/; |
|
624
|
18
|
|
|
|
|
82
|
my $ofh = select( $fh ); $| = 1; select ( $ofh ); # flush buffers |
|
|
18
|
|
|
|
|
45
|
|
|
|
18
|
|
|
|
|
48
|
|
|
625
|
18
|
50
|
|
|
|
173
|
flock $fh, LOCK_EX or croak qq/Can't lock exclusive $file: $!/; |
|
626
|
18
|
|
|
|
|
38
|
binmode $fh; |
|
627
|
|
|
|
|
|
|
|
|
628
|
18
|
|
|
|
|
67
|
$self->locked( $fh ); |
|
629
|
|
|
|
|
|
|
} |
|
630
|
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
632
|
|
|
|
|
|
|
# unlock() |
|
633
|
|
|
|
|
|
|
# closes the file handle -- the "lock token" in the object |
|
634
|
|
|
|
|
|
|
# |
|
635
|
|
|
|
|
|
|
# Private method. |
|
636
|
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
sub unlock { |
|
638
|
37
|
|
|
37
|
0
|
59
|
my( $self ) = @_; |
|
639
|
|
|
|
|
|
|
|
|
640
|
37
|
|
|
|
|
98
|
my $file = $self->dbm_lock_file; |
|
641
|
37
|
|
|
|
|
108
|
my $fh = $self->locked; |
|
642
|
|
|
|
|
|
|
|
|
643
|
37
|
50
|
|
|
|
456
|
close $fh or croak qq/Problem closing $file: $!/; |
|
644
|
|
|
|
|
|
|
} |
|
645
|
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
#--------------------------------------------------------------------- |
|
647
|
|
|
|
|
|
|
our $AUTOLOAD; |
|
648
|
|
|
|
|
|
|
sub AUTOLOAD { |
|
649
|
|
|
|
|
|
|
|
|
650
|
13
|
|
|
13
|
|
5663
|
my $method = $AUTOLOAD; |
|
651
|
13
|
|
|
|
|
70
|
$method =~ s/.*:://; |
|
652
|
13
|
|
|
|
|
26
|
for( $method ) { |
|
653
|
13
|
100
|
|
|
|
255
|
croak qq/Unsupported method: $_/ unless /^ |
|
654
|
|
|
|
|
|
|
name |
|
655
|
|
|
|
|
|
|
|dir |
|
656
|
|
|
|
|
|
|
|retrieve |
|
657
|
|
|
|
|
|
|
|retrieve_preamble |
|
658
|
|
|
|
|
|
|
|locate_record_data |
|
659
|
|
|
|
|
|
|
|history |
|
660
|
|
|
|
|
|
|
|userdata |
|
661
|
|
|
|
|
|
|
|howmany |
|
662
|
|
|
|
|
|
|
|lastkeynum |
|
663
|
|
|
|
|
|
|
|nextkeynum |
|
664
|
|
|
|
|
|
|
$/x; |
|
665
|
|
|
|
|
|
|
} |
|
666
|
|
|
|
|
|
|
|
|
667
|
12
|
|
|
|
|
21
|
my $self = shift; |
|
668
|
12
|
|
|
|
|
33
|
$self->datastore->$method( @_ ); |
|
669
|
|
|
|
|
|
|
} |
|
670
|
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
1; # returned |
|
672
|
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
__END__ |