Skip Menu |

This queue is for tickets about the DBM-Deep CPAN distribution.

Report information
The Basics
Id: 30079
Status: resolved
Priority: 0/
Queue: DBM-Deep

People
Owner: Nobody in particular
Requestors: stevensamelson [...] yahoo.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Optimization on a database using 'file_offset' fails
Date: Wed, 17 Oct 2007 22:22:52 -0700 (PDT)
To: bug-DBM-Deep [...] rt.cpan.org
From: Steven Samelson <stevensamelson [...] yahoo.com>
DBM::Deep version: 1.0006 Perl version: v5.8.8 built for MSWin32-x86-multi-thread OS version: Windows XP and Windows 2003 Server Bug Description: Optimizing databases with 'file_offset' larger than zero results in a very large database (100x larger). Optimization should retain the offset for the database, along with any data above the specified offset. Patch: Here is an inefficient work around. The comments with "Changed" indicate where some of the modifications were made (other comments were removed for sake of brevity): sub optimize { ## # Rebuild entire database into new file, then move # it back on top of original. ## my $self = shift->_get_self; #XXX Need to create a new test for this # if ($self->_storage->{links} > 1) { # $self->_throw_error("Cannot optimize: reference count is greater than 1"); # } #XXX Do we have to lock the tempfile? ##################################################################################### # Changed # This is to make sure that any database temp file that has been left from # the previous optimization has been deleted. ##################################################################################### my $file_offset = $self->_storage->{file_offset}; my $file = $self->_storage->{file}; my $new_db_name = $file . '.tmp'; unlink($new_db_name) if (-f $new_db_name); ##################################################################################### #XXX Should we use tempfile() here instead of a hard-coded name? my $db_temp = DBM:Deep->new( file => $self->_storage->{file} . '.tmp', type => $self->_type, # Bring over all the parameters that we need to bring over ( map { $_ => $self->_engine->$_ } qw( byte_size max_buckets data_sector_size num_txns )), file_offset => 0, # Changed sig_file => $sig_file, # Changed ); $self->lock(); $self->_engine->clear_cache; $self->_copy_node( $db_temp ); # Changed $db_temp->_storage->close; undef $db_temp; ## # Attempt to copy user, group and permissions over to new file ## my @stats = stat($self->_fh); my $perms = $stats[2] & 07777; my $uid = $stats[4]; my $gid = $stats[5]; chown( $uid, $gid, $self->_storage->{file} . '.tmp' ); chmod( $perms, $self->_storage->{file} . '.tmp' ); # q.v. perlport for more information on this variable if ( $^O eq 'MSWin32' || $^O eq 'cygwin' ) { ## # Potential race condition when optmizing on Win32 with locking. # The Windows filesystem requires that the filehandle be closed # before it is overwritten with rename(). This could be redone # with a soft copy. ## $self->unlock(); $self->_storage->close; } ################################################################################################ # Changed # Read the top part from the old database. ################################################################################################ # Copy the top part from the old db to the new db. my $top_part; my $fh_old; open $fh_old, $file; binmode $fh_old; my $rd = sysread($fh_old, $top_part, $file_offset); close $fh_old; ################################################################################################ if (!rename $self->_storage->{file} . '.tmp', $self->_storage->{file}) { unlink $self->_storage->{file} . '.tmp'; $self->unlock(); $self->_throw_error("Optimize failed: Cannot copy temp file over original: $!"); } $self->unlock(); $self->_storage->close; ################################################################################################ # Changed # Read the content of the database. ################################################################################################ my $db_content; # Get the actual size of the image my @array = stat("$file"); my $db_size = $array[7]; my $fh; open $fh, "$file"; binmode $fh; $rd = sysread($fh, $db_content, $db_size); close $fh; ################################################################################################ # Changed # Concatenate the top part with the database content and save it in the database. ############################################################################################### # Save it in the new db. my $fh_new; open $fh_new, ">$file"; binmode $fh_new; print $fh_new ($top_part . $db_content); close $fh_new; ################################################################################################ $self->_storage->open; $self->lock(); $self->_engine->setup_fh( $self ); $self->unlock(); return 1; } Show quoted text
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

Message body is not shown because it is too large.

I believe this was fixed in 1.0008. Is there any chance you could confirm that for me? On Thu Oct 18 01:23:33 2007, stevensamelson@yahoo.com wrote: Show quoted text
> DBM::Deep version: 1.0006 > Perl version: v5.8.8 built for MSWin32-x86-multi-thread > OS version: Windows XP and Windows 2003 Server > > Bug Description: > Optimizing databases with 'file_offset' larger than zero results in a > very large database (100x larger). Optimization should retain the > offset for the database, along with any data above the specified > offset. > > Patch: > Here is an inefficient work around. The comments with "Changed" > indicate where some of the modifications were made (other comments > were removed for sake of brevity): > > sub optimize { > ## > # Rebuild entire database into new file, then move > # it back on top of original. > ## > my $self = shift->_get_self; > > #XXX Need to create a new test for this > # if ($self->_storage->{links} > 1) { > # $self->_throw_error("Cannot optimize: reference count is > greater than 1"); > # } > > #XXX Do we have to lock the tempfile? > >
######################################################################## ############# Show quoted text
> # Changed > # This is to make sure that any database temp file that has been > left from > # the previous optimization has been deleted. >
######################################################################## ############# Show quoted text
> my $file_offset = $self->_storage->{file_offset}; > my $file = $self->_storage->{file}; > my $new_db_name = $file . '.tmp'; > unlink($new_db_name) if (-f $new_db_name); >
######################################################################## ############# Show quoted text
> > #XXX Should we use tempfile() here instead of a hard-coded name? > my $db_temp = DBM:Deep->new( > file => $self->_storage->{file} . '.tmp', > type => $self->_type, > > # Bring over all the parameters that we need to bring over > ( map { $_ => $self->_engine->$_ } qw( > byte_size max_buckets data_sector_size num_txns > )), > > file_offset => 0, # Changed > sig_file => $sig_file, # Changed > ); > > $self->lock(); > $self->_engine->clear_cache; > $self->_copy_node( $db_temp ); > > # Changed > $db_temp->_storage->close; > > undef $db_temp; > > ## > # Attempt to copy user, group and permissions over to new file > ## > my @stats = stat($self->_fh); > my $perms = $stats[2] & 07777; > my $uid = $stats[4]; > my $gid = $stats[5]; > chown( $uid, $gid, $self->_storage->{file} . '.tmp' ); > chmod( $perms, $self->_storage->{file} . '.tmp' ); > > # q.v. perlport for more information on this variable > if ( $^O eq 'MSWin32' || $^O eq 'cygwin' ) { > ## > # Potential race condition when optmizing on Win32 with > locking. > # The Windows filesystem requires that the filehandle be > closed > # before it is overwritten with rename(). This could be > redone > # with a soft copy. > ## > $self->unlock(); > $self->_storage->close; > } > >
######################################################################## ######################## Show quoted text
> # Changed > # Read the top part from the old database. >
######################################################################## ######################## Show quoted text
> # Copy the top part from the old db to the new db. > my $top_part; > my $fh_old; > open $fh_old, $file; > binmode $fh_old; > my $rd = sysread($fh_old, $top_part, $file_offset); > close $fh_old; >
######################################################################## ######################## Show quoted text
> if (!rename $self->_storage->{file} . '.tmp', $self->_storage-
> >{file}) {
> unlink $self->_storage->{file} . '.tmp'; > $self->unlock(); > $self->_throw_error("Optimize failed: Cannot copy temp file > over original: $!"); > } > > $self->unlock(); > $self->_storage->close; > >
######################################################################## ######################## Show quoted text
> # Changed > # Read the content of the database. >
######################################################################## ######################## Show quoted text
> my $db_content; > # Get the actual size of the image > my @array = stat("$file"); > my $db_size = $array[7]; > > my $fh; > open $fh, "$file"; > binmode $fh; > $rd = sysread($fh, $db_content, $db_size); > close $fh; >
######################################################################## ######################## Show quoted text
> # Changed > # Concatenate the top part with the database content and save it > in the database. >
######################################################################## ####################### Show quoted text
> # Save it in the new db. > my $fh_new; > open $fh_new, ">$file"; > binmode $fh_new; > print $fh_new ($top_part . $db_content); > close $fh_new; >
######################################################################## ######################## Show quoted text
> $self->_storage->open; > $self->lock(); > $self->_engine->setup_fh( $self ); > $self->unlock(); > > return 1; > } > > > __________________________________________________ > Do You Yahoo!? > Tired of spam? Yahoo! Mail has the best spam protection around > http://mail.yahoo.com