line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package AsciiDB::TagFile; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Copyright (c) 1997-2001 Jose A. Rodriguez. All rights reserved. |
4
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify it |
5
|
|
|
|
|
|
|
# under the same terms as Perl itself. |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
require Tie::Hash; |
8
|
|
|
|
|
|
|
@ISA = (Tie::Hash); |
9
|
|
|
|
|
|
|
|
10
|
6
|
|
|
6
|
|
5125
|
use Cwd; |
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
527
|
|
11
|
|
|
|
|
|
|
|
12
|
6
|
|
|
6
|
|
33
|
use vars qw($VERSION $catPathFileName); |
|
6
|
|
|
|
|
10
|
|
|
6
|
|
|
|
|
748
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
BEGIN { |
15
|
6
|
|
|
6
|
|
632
|
eval "use File::Spec"; |
|
6
|
|
|
6
|
|
40
|
|
|
6
|
|
|
|
|
11
|
|
|
6
|
|
|
|
|
77
|
|
16
|
|
|
|
|
|
|
$catPathFileName = ($@) ? |
17
|
0
|
|
|
|
|
0
|
sub { join('/', @_) } : # Unix way |
18
|
6
|
50
|
|
|
|
215
|
sub { File::Spec->catfile(@_) }; # Portable way |
|
175
|
|
|
|
|
194022
|
|
19
|
|
|
|
|
|
|
} |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
$VERSION = '1.06'; |
22
|
|
|
|
|
|
|
|
23
|
6
|
|
|
6
|
|
29
|
use Carp; |
|
6
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
4060
|
|
24
|
6
|
|
|
6
|
|
4346
|
use AsciiDB::TagRecord; |
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
7307
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub TIEHASH { |
27
|
6
|
|
|
6
|
|
4573
|
my $class = shift; |
28
|
6
|
|
|
|
|
34
|
my %params = @_; |
29
|
|
|
|
|
|
|
|
30
|
6
|
|
|
|
|
18
|
my $self = {}; |
31
|
6
|
|
33
|
|
|
41
|
$self->{_DIRECTORY} = $params{DIRECTORY} || cwd; |
32
|
6
|
|
50
|
|
|
32
|
$self->{_SUFIX} = $params{SUFIX} || ''; |
33
|
6
|
|
|
|
|
22
|
$self->{_SCHEMA} = $params{SCHEMA}; |
34
|
6
|
|
|
|
|
17
|
$self->{_READONLY} = $params{READONLY}; |
35
|
6
|
|
|
|
|
17
|
$self->{_FILEMODE} = $params{FILEMODE}; |
36
|
6
|
|
50
|
|
|
52
|
$self->{_LOCK} = $params{LOCK} || 0; |
37
|
6
|
|
|
|
|
18
|
$self->{_CACHESIZE} = $params{CACHESIZE}; |
38
|
|
|
|
|
|
|
|
39
|
6
|
50
|
|
|
|
91
|
unless (-d $self->{_DIRECTORY}) { |
40
|
0
|
|
|
|
|
0
|
croak "Directory '$params{DIRECTORY}' does not exist"; |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
6
|
100
|
|
|
|
28
|
if (defined $self->{_CACHESIZE}) { |
44
|
1
|
|
|
|
|
3
|
$self->{_CACHESIZE} = int($self->{_CACHESIZE}); |
45
|
|
|
|
|
|
|
|
46
|
1
|
50
|
|
|
|
7
|
if ($self->{_CACHESIZE} == 0) { |
|
|
50
|
|
|
|
|
|
47
|
0
|
|
|
|
|
0
|
undef $self->{_CACHESIZE}; |
48
|
|
|
|
|
|
|
} elsif ($self->{_CACHESIZE} < 1) { |
49
|
0
|
|
|
|
|
0
|
croak "Cache size should be >= 0 (0 means no cache)"; |
50
|
0
|
|
|
|
|
0
|
$self->{_CACHESIZE} = 1; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
# Number of internal keys (ie. '_key') |
55
|
6
|
|
|
|
|
29
|
$self->{_INTKEYCOUNT} = 1 + keys %$self; |
56
|
|
|
|
|
|
|
|
57
|
6
|
|
|
|
|
38
|
bless $self, $class; |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
sub FETCH { |
61
|
173
|
|
|
173
|
|
1605
|
my ($self, $key) = @_; |
62
|
|
|
|
|
|
|
|
63
|
173
|
100
|
|
|
|
615
|
return $self->{$key} if exists ($self->{$key}); |
64
|
|
|
|
|
|
|
|
65
|
108
|
|
|
|
|
203
|
return $self->newRecord($key); |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub STORE { |
69
|
2
|
|
|
2
|
|
4
|
my ($self, $key, $value) = @_; |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# Return if the user is assigning an object to itself ($a{A} = $a{A}) |
72
|
2
|
100
|
66
|
|
|
13
|
return if exists $self->{$key} && $self->{$key} == $value; |
73
|
|
|
|
|
|
|
|
74
|
1
|
50
|
|
|
|
6
|
$self->newRecord($key) unless (exists $self->{$key}); |
75
|
|
|
|
|
|
|
|
76
|
1
|
|
|
|
|
1
|
my $field; |
77
|
1
|
|
|
|
|
2
|
foreach $field (keys %{$self->{$key}}) { |
|
1
|
|
|
|
|
8
|
|
78
|
4
|
|
|
|
|
17
|
$self->{$key}{$field} = $value->{$field}; |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub FIRSTKEY { |
83
|
1
|
|
|
1
|
|
17
|
my $self = shift; |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# Current keys are the union of saved keys and new created but |
86
|
|
|
|
|
|
|
# not saved keys |
87
|
1
|
|
|
|
|
2
|
my %currentKeys; |
88
|
|
|
|
|
|
|
|
89
|
1
|
|
|
|
|
27
|
my $sufix = $self->{_SUFIX}; |
90
|
|
|
|
|
|
|
|
91
|
1
|
|
|
|
|
11
|
map { $currentKeys{$_} = 1 } |
|
1
|
|
|
|
|
5
|
|
92
|
2
|
|
|
|
|
41
|
map { $self->decodeKey($_) } |
93
|
1
|
|
|
|
|
6
|
grep { $_ =~ /(.+)\Q$sufix\E$/; $_ = $1 } |
|
2
|
|
|
|
|
11
|
|
94
|
|
|
|
|
|
|
$self->getDirFiles(); |
95
|
1
|
|
|
|
|
11
|
map { $currentKeys{$_} = 1 } grep(!/^_/, keys %$self); |
|
0
|
|
|
|
|
0
|
|
96
|
|
|
|
|
|
|
|
97
|
1
|
|
|
|
|
5
|
my @currentKeys = keys %currentKeys; |
98
|
1
|
|
|
|
|
3
|
$self->{_ITERATOR} = \@currentKeys; |
99
|
|
|
|
|
|
|
|
100
|
1
|
|
|
|
|
2
|
shift @{$self->{_ITERATOR}}; |
|
1
|
|
|
|
|
9
|
|
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
sub NEXTKEY { |
104
|
1
|
|
|
1
|
|
3
|
my $self = shift; |
105
|
|
|
|
|
|
|
|
106
|
1
|
|
|
|
|
2
|
shift @{$self->{_ITERATOR}}; |
|
1
|
|
|
|
|
7
|
|
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
sub EXISTS { |
110
|
2
|
|
|
2
|
|
18
|
my ($self, $key) = @_; |
111
|
|
|
|
|
|
|
|
112
|
2
|
100
|
66
|
|
|
13
|
$self->{$key} || -f $self->fileName($key) || 0; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub DELETE { |
116
|
55
|
|
|
55
|
|
328
|
my ($self, $key) = @_; |
117
|
|
|
|
|
|
|
|
118
|
55
|
100
|
|
|
|
109
|
return if $self->{_READONLY}; |
119
|
|
|
|
|
|
|
|
120
|
54
|
|
|
|
|
86
|
unlink $self->fileName($key); |
121
|
|
|
|
|
|
|
|
122
|
11
|
|
|
|
|
36
|
tied(%{$self->{$key}})->deleteRecord() |
|
54
|
|
|
|
|
187
|
|
123
|
54
|
100
|
|
|
|
119
|
if tied(%{$self->{$key}}); |
124
|
|
|
|
|
|
|
|
125
|
54
|
50
|
|
|
|
379
|
delete $self->{$key} if exists $self->{$key}; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
sub sync { |
129
|
1
|
|
|
1
|
0
|
7
|
my $self = shift; |
130
|
|
|
|
|
|
|
|
131
|
10
|
100
|
66
|
|
|
39
|
my @recordsToSync = grep { |
132
|
1
|
|
|
|
|
4
|
ref $_ && ref($_) eq 'HASH' && tied(%$_) |
133
|
1
|
|
|
|
|
2
|
} values %{$self}; |
134
|
|
|
|
|
|
|
|
135
|
1
|
|
|
|
|
2
|
my $record; |
136
|
1
|
|
|
|
|
2
|
foreach $record (@recordsToSync) { |
137
|
2
|
|
|
|
|
9
|
tied(%$record)->sync(); |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub purge { |
142
|
101
|
|
|
101
|
0
|
117
|
my $self = shift; |
143
|
101
|
|
|
|
|
100
|
my ($cacheSize) = @_; |
144
|
|
|
|
|
|
|
|
145
|
101
|
100
|
|
|
|
161
|
if (defined($cacheSize)) { |
146
|
100
|
|
|
|
|
143
|
my $dataRecords = scalar(keys %$self) - $self->{_INTKEYCOUNT}; |
147
|
100
|
100
|
|
|
|
224
|
return if $dataRecords < $cacheSize; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# This works in 5.004 no 5.003 |
151
|
|
|
|
|
|
|
#delete @$self{grep !/^_/, keys %{$self}}; |
152
|
|
|
|
|
|
|
# instead we use this... |
153
|
9
|
|
|
|
|
12
|
foreach (grep !/^_/, keys %{$self}) { |
|
9
|
|
|
|
|
108
|
|
154
|
90
|
|
|
|
|
281
|
delete $self->{$_}; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
sub newRecord { |
159
|
109
|
|
|
109
|
0
|
120
|
my $self = shift; |
160
|
109
|
|
|
|
|
120
|
my ($key) = @_; |
161
|
|
|
|
|
|
|
|
162
|
109
|
100
|
|
|
|
307
|
$self->purge($self->{_CACHESIZE}) if defined($self->{_CACHESIZE}); |
163
|
|
|
|
|
|
|
|
164
|
109
|
|
|
|
|
128
|
my %record; |
165
|
109
|
|
|
|
|
201
|
tie %record, 'AsciiDB::TagRecord', |
166
|
|
|
|
|
|
|
FILENAME => $self->fileName($key), |
167
|
|
|
|
|
|
|
SCHEMA => $self->{_SCHEMA}, |
168
|
|
|
|
|
|
|
READONLY => $self->{_READONLY}, |
169
|
|
|
|
|
|
|
FILEMODE => $self->{_FILEMODE}; |
170
|
|
|
|
|
|
|
|
171
|
109
|
|
|
|
|
776
|
$self->{$key} = \%record; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub encodeKey { |
175
|
171
|
|
|
171
|
0
|
159
|
my $self = shift; |
176
|
171
|
|
|
|
|
194
|
my ($key) = @_; |
177
|
|
|
|
|
|
|
|
178
|
171
|
|
|
|
|
331
|
my $encodeSub = $self->{_SCHEMA}{KEY}{ENCODE}; |
179
|
171
|
50
|
|
|
|
424
|
($encodeSub) ? &$encodeSub($key) : $key; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
sub decodeKey { |
183
|
1
|
|
|
1
|
0
|
3
|
my $self = shift; |
184
|
1
|
|
|
|
|
3
|
my ($key) = @_; |
185
|
|
|
|
|
|
|
|
186
|
1
|
|
|
|
|
3
|
my $decodeSub = $self->{_SCHEMA}{KEY}{DECODE}; |
187
|
1
|
50
|
|
|
|
8
|
($decodeSub) ? &$decodeSub($key) : $key; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub fileName { |
191
|
171
|
|
|
171
|
0
|
241
|
my $self = shift; |
192
|
171
|
|
|
|
|
311
|
my ($key) = $self->encodeKey(@_); |
193
|
|
|
|
|
|
|
|
194
|
171
|
|
|
|
|
1021
|
&$catPathFileName($$self{_DIRECTORY}, "$key$$self{_SUFIX}") |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub getDirFiles { |
198
|
1
|
|
|
1
|
0
|
2
|
my $self = shift; |
199
|
|
|
|
|
|
|
|
200
|
1
|
|
|
|
|
5
|
local *DIR; |
201
|
1
|
50
|
|
|
|
70
|
opendir(DIR, $$self{_DIRECTORY}) |
202
|
|
|
|
|
|
|
|| die "Can't opendir $$self{_DIRECTORY}: $!"; |
203
|
1
|
|
|
|
|
42
|
my @files = grep { -f &$catPathFileName($$self{_DIRECTORY}, $_) } |
|
4
|
|
|
|
|
10
|
|
204
|
|
|
|
|
|
|
readdir(DIR); |
205
|
1
|
|
|
|
|
19
|
closedir DIR; |
206
|
|
|
|
|
|
|
|
207
|
1
|
|
|
|
|
6
|
@files; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
1; |
211
|
|
|
|
|
|
|
__END__ |