/[wait]/branches/CPAN/lib/WAIT/Database.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /branches/CPAN/lib/WAIT/Database.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (show annotations)
Fri Apr 28 15:42:44 2000 UTC (24 years ago) by ulpfr
File size: 7794 byte(s)
Import of WAIT-1.710

1 # -*- Mode: Cperl -*-
2 # Database --
3 # ITIID : $ITI$ $Header $__Header$
4 # Author : Ulrich Pfeifer
5 # Created On : Thu Aug 8 09:44:13 1996
6 # Last Modified By: Ulrich Pfeifer
7 # Last Modified On: Sun May 30 18:34:08 1999
8 # Language : CPerl
9 # Update Count : 250
10 # Status : Unknown, Use with caution!
11 #
12 # Copyright (c) 1996-1997, Ulrich Pfeifer
13 #
14
15 =head1 NAME
16
17 WAIT::Database - Module fo maintaining WAIT databases
18
19 =head1 SYNOPSIS
20
21 require WAIT::Database;
22
23 =head1 DESCRIPTION
24
25 The modules handles creating, opening, and deleting of databases and
26 tables.
27
28 =cut
29
30 package WAIT::Database;
31
32 use strict;
33 use FileHandle ();
34 use File::Path qw(rmtree);
35 use WAIT::Table ();
36 use Fcntl;
37 use Carp; # will use autouse later
38 # use autouse Carp => qw( croak($) );
39 my ($HAVE_DATA_DUMPER, $HAVE_STORABLE);
40
41 BEGIN {
42 eval { require Data::Dumper };
43 $HAVE_DATA_DUMPER = 1 if $@ eq '';
44 eval { require Storable };
45 $HAVE_STORABLE = 1 if $@ eq '';
46 $HAVE_DATA_DUMPER || $HAVE_STORABLE ||
47 die "Could not find Data::Dumper nor Storable";
48 $Storable::forgive_me = 1;
49 }
50
51
52 =head2 Constructor create
53
54 $db = WAIT::Database->create(
55 name => <name>,
56 directory => <dir>
57 );
58
59 Create a new database.
60
61 =over 10
62
63 =item B<name> I<name>
64
65 mandatory
66
67 =item B<directory> I<directory>
68
69 Directory which should contain the database (defaults to the current
70 directory).
71
72 =item B<uniqueatt> I<true>
73
74 If given, the database will require unique attributes over all tables.
75
76 The method will croak on failure.
77
78 =back
79
80 =cut
81
82 sub create {
83 my $type = shift;
84 my %parm = @_;
85 my $self = {};
86 my $dir = $parm{directory} || '.';
87 my $name = $parm{name};
88
89 unless ($name) {
90 croak("No name specified");
91 }
92
93 unless (-d $dir){
94 croak("Directory '$dir' does not exits: $!");
95 }
96
97 if (-d "$dir/$name") {
98 warn "Warning: Directory '$dir/$name' already exists";
99 } else {
100 unless (mkdir "$dir/$name", 0775) {
101 croak("Could not mkdir '$dir/$name': $!");
102 }
103 }
104
105 $self->{name} = $name;
106 $self->{file} = "$dir/$name";
107 $self->{uniqueatt} = $parm{uniqueatt};
108 $self->{mode} = O_CREAT;
109 bless $self => ref($type) || $type;
110 }
111
112
113 =head2 Constructor open
114
115 $db = WAIT::Database->open(
116 name => "foo",
117 directory => "bar"
118 );
119
120 Open an existing database I<foo> in directory I<bar>.
121
122 =cut
123
124 sub open {
125 my $type = shift;
126 my %parm = @_;
127 my $dir = $parm{directory} || '.';
128 my $name = $parm{name} or croak "No name specified";
129 my $catalog = "$dir/$name/catalog";
130 my $meta = "$dir/$name/meta";
131 my $self;
132
133 if ($HAVE_STORABLE and -e $catalog
134 and (!-e $meta or -M $meta >= -M $catalog)) {
135 $self = Storable::retrieve($catalog);
136 } else {
137 return undef unless -f $meta;
138
139 $self = do $meta;
140 unless (defined $self) {
141 warn "do '$meta' did not work. Mysterious! Reverting to eval `cat $meta`";
142 sleep(4);
143 $self = eval `cat $meta`;
144 }
145 }
146
147 return unless defined $self;
148 $self->{mode} = (exists $parm{mode})?$parm{mode}:(O_CREAT | O_RDWR);
149 $self;
150 }
151
152
153 =head2 C<$db-E<gt>dispose;>
154
155 Dispose a database. Remove all associated files. This may fail if the
156 database or one of its tables is still open. Failure will be indicated
157 by a false return value.
158
159 =cut
160
161 sub dispose {
162 my $dir;
163
164 if (ref $_[0]) { # called with instance
165 croak "Database readonly" unless $_[0]->{mode} & (O_CREAT | O_RDWR);
166 $dir = $_[0]->{file};
167 $_[0]->close;
168 } else {
169 my $type = shift;
170 my %parm = @_;
171 my $base = $parm{directory} || '.';
172 my $name = $parm{name} || croak "No name specified";
173 $dir = "$base/$name";
174 }
175 croak "No such database '$dir'" unless -e "$dir/meta";
176
177 #warn "Running rmtree on dir[$dir]";
178 my $ret = rmtree($dir, 0, 1);
179 #warn "rmtree returned[$ret]";
180 $ret;
181 }
182
183
184 =head2 C<$db-E<gt>close;>
185
186 Close a database saving all meta data after closing all associated tables.
187
188 =cut
189
190 sub close {
191 my $self = $_[0];
192 my $file = $self->{file};
193 my $table;
194 my $did_save;
195
196 for $table (values %{$self->{tables}}) {
197 $table->close if ref($table);
198 }
199 return 1 unless $self->{mode} & (O_RDWR | O_CREAT);
200
201 if ($HAVE_DATA_DUMPER) {
202 my $fh = new FileHandle "> $file/meta";
203 if ($fh) {
204 my $dumper = new Data::Dumper [$self],['self'];
205 $fh->print('my ');
206 $fh->print($dumper->Dumpxs);
207 $fh->close;
208 $did_save = 1;
209 } else {
210 croak "Could not open '$file/meta' for writing: $!";
211 # never reached: return unless $HAVE_STORABLE;
212 }
213 }
214
215 if ($HAVE_STORABLE) {
216 if (!eval {Storable::store($self, "$file/catalog")}) {
217 croak "Could not open '$file/catalog' for writing: $!";
218 # never reached: return unless $did_save;
219 } else {
220 $did_save++;
221 }
222 }
223 undef $_[0];
224 $did_save;
225 }
226
227
228 =head2 C<$db-E<gt>create_table(name =E<gt>> I<tname>, ... C<);>
229
230 Create a new table with name I<tname>. All parameters are passed to
231 C<WAIT::Table-E<gt>new> together with a filename to use. See
232 L<WAIT::Table> for which attributes are required. The method returns a
233 table handle (C<WAIT::Table::Handle>).
234
235 =cut
236
237 sub create_table {
238 my $self = shift;
239 my %parm = @_;
240 my $name = $parm{name} or croak "create_table: No name specified";
241 my $attr = $parm{attr} or croak "create_table: No attributes specified";
242 my $file = $self->{file};
243
244 croak "Database readonly" unless $self->{mode} & (O_CREAT | O_RDWR);
245
246 if (defined $self->{tables}->{$name}) {
247 die "Table '$name' already exists";
248 }
249
250 if ($self->{uniqueatt}) {
251 for (@$attr) { # attribute names must be uniqe
252 if ($self->{attr}->{$_}) {
253 croak("Attribute '$_' is not unique")
254 }
255 }
256 }
257 $self->{tables}->{$name} = WAIT::Table->new(file => "$file/$name",
258 database => $self,
259 %parm);
260 unless (defined $self->{tables}->{$name}) {# fail gracefully
261 delete $self->{tables}->{$name};
262 return undef;
263 }
264
265 if ($self->{uniqueatt}) {
266 # remember table name for each attribute
267 map ($self->{attr}->{$_} = $name, @$attr);
268 }
269 WAIT::Table::Handle->new($self, $name);
270 }
271
272
273 =head2 C<$db-E<gt>table(name =E<gt>> I<tname>C<);>
274
275 Open a new table with name I<tname>. The method
276 returns a table handle (C<WAIT::Table::Handle).
277
278 =cut
279
280 sub sync {
281 my $self = shift;
282
283 for (values %{$self->{tables}}) {
284 $_->sync;
285 }
286 }
287
288 sub table {
289 my $self = shift;
290 my %parm = @_;
291 my $name = $parm{name} or croak "No name specified";
292
293 if (defined $self->{tables}->{$name}) {
294 if (exists $parm{mode}) {
295 $self->{tables}->{$name}->{mode} = $parm{mode};
296 } else {
297 $self->{tables}->{$name}->{mode} = $self->{mode};
298 }
299 WAIT::Table::Handle->new($self,$name);
300 } else {
301 croak "No such table '$name'";
302 }
303 }
304
305
306 =head2 C<$db-E<gt>drop(name =E<gt>> I<tname>C<);>
307
308 Drop the table named I<tname>. The table should be closed before
309 calling B<drop>.
310
311 =cut
312
313 sub drop_table {
314 my $self = shift;
315 my %parm = @_;
316 my $name = $parm{name} or croak "No name specified";
317
318 croak "Database readonly" unless $self->{mode} & (O_CREAT | O_RDWR);
319 if (!defined $self->{tables}->{$name}) {
320 croak "Table '$name' does not exist";
321 }
322 $self->{tables}->{$name}->drop;
323
324 if ($self->{uniqueatt}) {
325 # recycle attribute names
326 for (keys %{$self->{attr}}) {
327 delete $self->{attr}->{$_} if $self->{attr}->{$_} eq $name;
328 }
329 }
330 undef $self->{tables}->{$name}; # Call WAIT::Table::DESTROY here;
331 1;
332 }
333
334
335 1;
336
337
338 =head1 AUTHOR
339
340 Ulrich Pfeifer E<lt>F<pfeifer@ls6.informatik.uni-dortmund.de>E<gt>
341
342 =cut
343
344

Properties

Name Value
cvs2svn:cvs-rev 1.1.1.2

  ViewVC Help
Powered by ViewVC 1.1.26