init
This commit is contained in:
198
wcmtools/mogilefs/server/mogstored
Executable file
198
wcmtools/mogilefs/server/mogstored
Executable file
@@ -0,0 +1,198 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
|
||||
if 0; # not running under some shell
|
||||
|
||||
#
|
||||
# MogileFS storage node daemon
|
||||
# (perlbal front-end)
|
||||
#
|
||||
# (c) 2004, Brad Fitzpatrick, <brad@danga.com>
|
||||
|
||||
use strict;
|
||||
use lib 'lib';
|
||||
use Perlbal;
|
||||
use Linux::AIO '1.3';
|
||||
use IO::Socket::INET;
|
||||
|
||||
my $opt_daemonize;
|
||||
my $opt_config;
|
||||
exit 1 unless
|
||||
Getopt::Long::GetOptions(
|
||||
'daemon' => \$opt_daemonize,
|
||||
'config=s' => \$opt_config,
|
||||
);
|
||||
|
||||
my $default_config = "/etc/mogilefs/mogstored.conf";
|
||||
$opt_config = $default_config if ! $opt_config && -e $default_config;
|
||||
|
||||
my $conf;
|
||||
if (-e $opt_config) {
|
||||
if (open F, $opt_config) {
|
||||
local $/ = undef;
|
||||
$conf = <F>;
|
||||
close F;
|
||||
} else {
|
||||
die "Couldn't open config file ($opt_config): $!\n";
|
||||
}
|
||||
}
|
||||
|
||||
my $out = sub { print STDOUT join("\n", map { ref $_ eq 'ARRAY' ? @$_ : $_ } @_) . "\n"; };
|
||||
|
||||
my $path = "/var/mogdata";
|
||||
my $listen = "0.0.0.0:7500";
|
||||
|
||||
$conf ||= "
|
||||
SERVER max_connections = 10000
|
||||
CREATE SERVICE mogstored
|
||||
SET mogstored.role = web_server
|
||||
SET mogstored.listen = $listen
|
||||
SET mogstored.docroot = $path
|
||||
SET mogstored.dirindexing = 0
|
||||
SET mogstored.enable_put = 1
|
||||
SET mogstored.enable_delete = 1
|
||||
SET mogstored.min_put_directory = 1
|
||||
SET mogstored.persist_client = 1
|
||||
ENABLE mogstored
|
||||
";
|
||||
|
||||
Perlbal::run_manage_command($_, $out) foreach split(/\n/, $conf);
|
||||
|
||||
unless (Perlbal::Socket->WatchedSockets() > 0) {
|
||||
die "Invalid configuration. (shouldn't happen?) Stopping.\n";
|
||||
}
|
||||
|
||||
if ($opt_daemonize) {
|
||||
Perlbal::daemonize();
|
||||
} else {
|
||||
print "Running.\n";
|
||||
}
|
||||
|
||||
# register our disk usage callback to get disk usage and keep an eye on how we're doing
|
||||
Perlbal::Socket::register_callback(1, sub {
|
||||
my $err = sub { Perlbal::log('crit', $_[0]); return 60; };
|
||||
my $rval = `df -l`;
|
||||
foreach my $l (split /\r?\n/, $rval) {
|
||||
next unless $l =~ /^(.+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(.+)\s+(.+)$/;
|
||||
my ($dev, $total, $used, $avail, $use, $disk) = ($1, $2, $3, $4, $5, $6);
|
||||
next unless $disk =~ /^$path/;
|
||||
|
||||
# create string to print
|
||||
my $now = time;
|
||||
my $output = "time: $now\ndevice: $dev\ntotal: $total\nused: $used\navailable: $avail\nuse: $use\ndisk: $disk\n";
|
||||
|
||||
# open a file on that disk location called 'usage'
|
||||
my $rv = open(FILE, ">$disk/usage");
|
||||
unless ($rv) {
|
||||
$err->("Unable to open '$disk/usage' for writing: $!");
|
||||
next;
|
||||
}
|
||||
print FILE $output;
|
||||
close FILE;
|
||||
|
||||
}
|
||||
return 60;
|
||||
});
|
||||
|
||||
# setup a new socket for handling size requests
|
||||
my $server = IO::Socket::INET->new(LocalPort => 7501, # FIXME make this configurable
|
||||
Type => SOCK_STREAM,
|
||||
Proto => 'tcp',
|
||||
Blocking => 0,
|
||||
Reuse => 1,
|
||||
Listen => 10 )
|
||||
or die "Error creating socket: $@\n";
|
||||
|
||||
# in Perl 5.6, we weren't always seeing this turned off by IO::Socket
|
||||
# so we have to do it manually here just to be sure.
|
||||
IO::Handle::blocking($server, 0);
|
||||
|
||||
# accept handler for new workers
|
||||
my $accept_handler = sub {
|
||||
my $csock = $server->accept()
|
||||
or return;
|
||||
IO::Handle::blocking($csock, 0);
|
||||
my $client = SideChannelClient->new($csock);
|
||||
$client->watch_read(1);
|
||||
# ... that's it. Client->new adds to event loop.
|
||||
};
|
||||
|
||||
# add to fd list so this one gets processed
|
||||
Perlbal::Socket->AddOtherFds(fileno($server) => $accept_handler);
|
||||
|
||||
# now start the main loop
|
||||
Perlbal::run();
|
||||
|
||||
#############################################################################
|
||||
### simple package for handling the stream request port
|
||||
package SideChannelClient;
|
||||
|
||||
use base qw{Perlbal::Socket};
|
||||
use fields qw{count};
|
||||
|
||||
# needed since we're pretending to be a Perlbal::Socket... never idle out
|
||||
sub max_idle_time { return 0; }
|
||||
|
||||
sub new {
|
||||
my SideChannelClient $self = shift;
|
||||
$self = fields::new($self) unless ref $self;
|
||||
$self->SUPER::new(@_);
|
||||
$self->state('side_channel');
|
||||
$self->{count} = 0;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub event_read {
|
||||
my SideChannelClient $self = shift;
|
||||
|
||||
my $bref = $self->read(1024);
|
||||
return $self->close() unless defined $bref;
|
||||
$self->{read_buf} .= $$bref;
|
||||
|
||||
while ($self->{read_buf} =~ s/^(.+?)\r?\n//) {
|
||||
my $cmd = $1;
|
||||
if ($cmd =~ /^size (\S+)$/) {
|
||||
# increase our count
|
||||
$self->{count}++;
|
||||
|
||||
# validate uri
|
||||
my $uri = $1;
|
||||
if ($uri =~ /\.\./) {
|
||||
$self->write("ERROR: uri invalid (contains ..)\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
# now stat the file to get the size and such
|
||||
Linux::AIO::aio_stat("$path$uri", sub {
|
||||
return if $self->{closed};
|
||||
my $size = -e _ ? -s _ : -1;
|
||||
$self->write("$uri $size\r\n");
|
||||
});
|
||||
} else {
|
||||
# we don't understand this so pass it on to manage command interface
|
||||
my @out;
|
||||
Perlbal::run_manage_command($cmd, sub { push @out, $_[0]; });
|
||||
$self->write(join("\r\n", @out) . "\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# override Danga::Socket's event handlers which die
|
||||
sub event_err { $_[0]->close; }
|
||||
sub event_hup { $_[0]->close; }
|
||||
|
||||
# as_string handler
|
||||
sub as_string {
|
||||
my SideChannelClient $self = shift;
|
||||
|
||||
my $ret = $self->SUPER::as_string;
|
||||
$ret .= "; size_requests=$self->{count}";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
# Local Variables:
|
||||
# mode: perl
|
||||
# c-basic-indent: 4
|
||||
# indent-tabs-mode: nil
|
||||
# End:
|
||||
Reference in New Issue
Block a user