Skip to content

Commit

Permalink
Ubic::AtomicFile module
Browse files Browse the repository at this point in the history
  • Loading branch information
Vyacheslav Matyukhin committed Jun 14, 2011
1 parent bf6c61b commit da29374
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 18 deletions.
6 changes: 2 additions & 4 deletions lib/Ubic.pm
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use Ubic::Multiservice::Dir;
use Ubic::AccessGuard;
use Ubic::Credentials;
use Ubic::Persistent;
use Ubic::AtomicFile;
use Ubic::SingletonLock;
use Ubic::Settings;

Expand Down Expand Up @@ -727,12 +728,9 @@ sub forked_call {
};

try {
open my $fh, '>', "$tmp_file.tmp" or die "Can't write to '$tmp_file.tmp: $!";
print {$fh} freeze($result);
close $fh or die "Can't close $tmp_file.tmp: $!";
Ubic::AtomicFile::store( freeze($result) => $tmp_file );
STDOUT->flush;
STDERR->flush;
rename "$tmp_file.tmp", $tmp_file;
POSIX::_exit(0); # don't allow to lock to be released - this process was forked from unknown environment, don't want to run unknown destructors
}
catch {
Expand Down
5 changes: 2 additions & 3 deletions lib/Ubic/Admin/Setup.pm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use Getopt::Long 2.33;
use Carp;
use IPC::Open3;

use Ubic::AtomicFile;
use Ubic::Settings;
use Ubic::Settings::ConfigFile;

Expand Down Expand Up @@ -299,9 +300,7 @@ sub setup {
print "Installing ubic.$name service...\n";

my $file = "$service_dir/ubic/$name";
open my $fh, '>', $file or die "Can't write to '$file': $!";
print {$fh} $content or die "Can't write to '$file': $!";
close $fh or die "Can't close '$file': $!";
Ubic::AtomicFile::store($content => $file);
};

$add_service->(
Expand Down
40 changes: 40 additions & 0 deletions lib/Ubic/AtomicFile.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package Ubic::AtomicFile;

use strict;
use warnings;

# ABSTRACT: atomic file operations

=head1 SYNOPSIS
use Ubic::AtomicFile;
Ubic::AtomicFile::store("blah\n" => "/var/lib/blah");
=head1 FUNCTIONS
=over
=item B<store($data, $file)>
Store C<$data> into C<$file> atomically. Temporary C<$file.new> will be created and then renamed to C<$file>.
=cut
sub store($$) {
my ($data, $file) = @_;

my $new_file = "$file.new";

# here is an interesting link explaining why we need to do it this way:
# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/317781/comments/54
open my $fh, '>', $new_file or die "Can't open '$new_file' for writing: $!";
print {$fh} $data or die "Can't print to '$new_file': $!";
$fh->flush or die "Can't flush '$new_file': $!";
close $fh or die "Can't close '$new_file': $!";
rename $new_file => $file or die "Can't rename '$new_file' to '$file': $!";
}
=back
=cut

1;
15 changes: 8 additions & 7 deletions lib/Ubic/Daemon/PidState.pm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use warnings;

use Params::Validate qw(:all);
use Ubic::Lockf;
use Ubic::AtomicFile;

use overload '""' => sub {
my $self = shift;
Expand Down Expand Up @@ -176,13 +177,13 @@ sub write {

my ($pid, $guid) = @$params{qw/ pid guid /};
my $self_pid = $$;
open my $fh, '>', "$dir/pid.new" or die "Can't write '$dir/pid.new': $!";
print {$fh} "pid $self_pid\n";
print {$fh} "guid $guid\n";
print {$fh} "daemon $pid\n";
$fh->flush;
close $fh or die "Can't close '$dir/pid.new': $!";
rename "$dir/pid.new" => "$dir/pid" or die "Can't commit pidfile $dir: $!";

Ubic::AtomicFile::store(
"pid $self_pid\n".
"guid $guid\n".
"daemon $pid\n"
=> "$dir/pid"
);
}

=back
Expand Down
6 changes: 2 additions & 4 deletions lib/Ubic/Persistent.pm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use warnings;

use JSON;
use Ubic::Lockf;
use Ubic::AtomicFile;

{
# JSON.pm v2 incompatibility with v1 is really, really annoying.
Expand Down Expand Up @@ -92,11 +93,8 @@ Write data back on disk.
sub commit {
my $self = shift;
my $fname = $meta->{$self}{fname};
open my $tmp_fh, '>', "$fname.new" or die "Can't write '$fname.new': $!";

print {$tmp_fh} objToJson({ %$self });
close $tmp_fh or die "Can't write to '$fname.new': $!";
rename "$fname.new" => $fname or die "Can't rename '$fname.new' to '$fname': $!";
Ubic::AtomicFile::store(objToJson({ %$self }) => $fname);
}

sub DESTROY {
Expand Down

0 comments on commit da29374

Please sign in to comment.