#!/usr/bin/perl ################################################################################ # $Id: fluxd.pl 3296 2007-12-03 20:45:41Z lordnor $ # $Date: 2007-12-03 14:45:41 -0600 (Mon, 03 Dec 2007) $ # $Revision: 3296 $ ################################################################################ # # # LICENSE # # # # This program is free software; you can redistribute it and/or # # modify it under the terms of the GNU General Public License (GPL) # # as published by the Free Software Foundation; either version 2 # # of the License, or (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # To read the license please visit http://www.gnu.org/copyleft/gpl.html # # # # # ################################################################################ # # # Requirements : # # * IO::Select ( perl -MCPAN -e "install IO::Select" ) # # * IO::Socket::UNIX ( perl -MCPAN -e "install IO::Socket::UNIX" ) # # * IO::Socket::INET ( perl -MCPAN -e "install IO::Socket::INET" ) # # * POSIX ( perl -MCPAN -e "install POSIX" ) # # # ################################################################################ package Fluxd; use strict; use warnings; use FluxCommon; use StatFile; ################################################################################ ################################################################################ # fields # ################################################################################ # constants use constant MOD_STATE_ERROR => -1; use constant MOD_STATE_NULL => 0; use constant MOD_STATE_OK => 1; # files and dirs my $path_data_dir = ".fluxd"; my $path_transfer_dir = ".transfers"; my $bin_fluxcli = "fluxcli.php"; my $path_socket = "fluxd.sock"; my $log_error = "fluxd-error.log"; my $log = "fluxd.log"; my $file_pid = "fluxd.pid"; my $file_conf = "fluxd.conf"; # defaults my $loglevel = 0; my $path_docroot = "/var/www/"; my $path_path = "/usr/local/torrentflux/"; my $bin_php = "/usr/bin/php"; my $dbMode = "dbi"; # delims of modList my $delimMod = ";"; my $delimState = ":"; # internal vars my ($VERSION, $DIR, $PROG, $EXTENSION); my $server; my $select; my $start_time = time(); my $start_time_local = localtime(); my $loop = 1; # db-bean my $fluxDB; # service-modules our %serviceModules; our %serviceModuleNames; my %serviceModuleObjects; ################################################################################ # main # ################################################################################ # flush the buffer $| = 1; # initialize initialize(); # process arguments processArguments(); # daemon-startup daemonStartup(); # daemon-main daemonMain(); # daemon-shutdown daemonShutdown(); ################################################################################ # subs # ################################################################################ #------------------------------------------------------------------------------# # Sub: initialize # # Arguments: Null # # Returns: Null # #------------------------------------------------------------------------------# sub initialize { # initialize some variables $VERSION = do { my @r = (q$Revision: 3296 $ =~ /\d+/g); sprintf "%d"."%02d" x $#r, @r }; ($DIR=$0) =~ s/([^\/\\]*)$//; ($PROG=$1) =~ s/\.([^\.]*)$//; $EXTENSION = $1; # load fluxd-conf eval 'require "'.$file_conf.'";'; if ($@) { print STDERR "failed to load config-file ".$file_conf."\n"; exit; } # fill name-list foreach my $smod (sort keys %serviceModules) { $serviceModuleNames{$serviceModules{$smod}{"name"}} = 1; } } #------------------------------------------------------------------------------# # Sub: processArguments # # Arguments: Null # # Returns: Null # #------------------------------------------------------------------------------# sub processArguments { my $temp = shift @ARGV; # first arg is operation. if (!(defined $temp)) { printUsage(); exit; } # help if ($temp =~ /.*(help|-h).*/) { printUsage(); exit; } # version if ($temp =~ /.*(version|-v).*/) { printVersion(); exit; }; # check if ($temp =~ /check/) { check(); exit; }; # debug if ($temp =~ /debug/) { debug(); exit; }; # daemon-stop if ($temp =~ /stop/) { # path_docroot $temp = shift @ARGV; if (!(defined $temp)) { printUsage(); exit; } if (!((substr $temp, -1) eq "/")) { $temp .= "/"; } $path_docroot = $temp; # path_path $temp = shift @ARGV; if (!(defined $temp)) { printUsage(); exit; } if (!((substr $temp, -1) eq "/")) { $temp .= "/"; } $path_path = $temp; # bin_php $temp = shift @ARGV; if (!(defined $temp)) { printUsage(); exit; } $bin_php = $temp; # dbMode $temp = shift @ARGV; if (!(defined $temp)) { printUsage(); exit; } $dbMode = $temp; # init paths initPaths(); # check if running if (daemonIsRunning($path_docroot) == 0) { printError("CORE", "daemon not running.\n"); exit; } printMessage("CORE", "Stopping daemon...\n"); # shutdown if (-f $file_pid) { # get pid open(PIDFILE,"< $file_pid"); my $daemonPid = ; close(PIDFILE); chomp $daemonPid; # send TERM to daemon kill 'SIGTERM', $daemonPid; } else { printError("CORE", "Error : cant find pid-file (".$file_pid."), daemon running ?\n"); } # exit exit; }; # start if ($temp =~ /start/) { # path_docroot $temp = shift @ARGV; if (!(defined $temp)) { printUsage(); exit; } if (!((substr $temp, -1) eq "/")) { $temp .= "/"; } $path_docroot = $temp; # path_path $temp = shift @ARGV; if (!(defined $temp)) { printUsage(); exit; } if (!((substr $temp, -1) eq "/")) { $temp .= "/"; } $path_path = $temp; # bin_php $temp = shift @ARGV; if (!(defined $temp)) { printUsage(); exit; } $bin_php = $temp; # dbMode $temp = shift @ARGV; if (!(defined $temp)) { printUsage(); exit; } $dbMode = $temp; # init paths initPaths(); # return return 1; }; # hmmm dont know this arg, show usage screen printUsage(); exit; } #------------------------------------------------------------------------------# # Sub: daemonStartup # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub daemonStartup { # print printMessage("CORE", "fluxd starting...\n"); # daemonise the script &daemonize(); # load flux-service-modules serviceModulesLoad(); # print that we started ok printMessage("CORE", "fluxd-startup complete. fluxd is up and running.\n"); } #------------------------------------------------------------------------------# # Sub: daemonize # # Arguments: Null # # Returns: Null # #------------------------------------------------------------------------------# sub daemonize { # umask umask 0; # STD-IN/OUT/ERR # STDIN unless (open STDIN, "/dev/null") { logError("CORE", "failed to open STDIN: ".$!."\n"); exit; } # STDOUT unless (open STDOUT, ">>$log") { logError("CORE", "failed to open STDOUT: ".$!."\n"); exit; } # STDERR unless (open STDERR, ">>$log_error") { logError("CORE", "failed to open STDERR: ".$!."\n"); exit; } # check if already running if (daemonIsRunning($path_docroot) == 1) { printError("CORE", "daemon already running.\n"); exit; } # check for pid-file if (-f $file_pid) { printMessage("CORE", "pid-file (".$file_pid.") exists but daemon not running. deleting...\n"); pidFileDelete(); } # check for socket if (-r $path_socket) { printMessage("CORE", "socket (".$path_socket.") exists but daemon not running. deleting...\n"); socketRemove(); } # load perl-modules loadModules(); # print printMessage("CORE", "initialize FluxDB...\n"); # db-bean require FluxDB; # create instance $fluxDB = FluxDB->new(); # initialize $fluxDB->initialize($path_docroot, $bin_php, $dbMode); if ($fluxDB->getState() != MOD_STATE_OK) { printError("CORE", "Error : initializing FluxDB : ".$fluxDB->getMessage()."\n"); exit; } # loglevel $loglevel = FluxDB->getFluxConfig("fluxd_loglevel"); # chdir #chdir($path_docroot) or die "Can't chdir to docroot: $!"; # fork if ($loglevel > 1) { printMessage("CORE", "forking and starting a new session...\n"); } my $pid = fork; unless (defined($pid)) { printError("CORE", "could not fork: ".$!."\n"); exit; } exit if $pid; unless (POSIX::setsid()) { printError("CORE", "could not start a new session: ".$!."\n"); exit; } # log printMessage("CORE", "daemon starting with docroot ".$path_docroot." (pid: ".$$.")\n"); # set up our signal handlers if ($loglevel > 1) { printMessage("CORE", "setting up signal handlers...\n"); } $SIG{HUP} = \&gotSigHup; $SIG{INT} = \&gotSigInt; $SIG{TERM} = \&gotSigTerm; $SIG{QUIT} = \&gotSigQuit; # set up server socket socketInitialize(); # write out pid-file pidFileWrite($$); } #------------------------------------------------------------------------------# # Sub: daemonMain # # Arguments: Null # # Returns: Null # #------------------------------------------------------------------------------# sub daemonMain { # loop while ($loop) { # check Connections checkConnections(); # service-modules main-methods foreach my $smod (sort keys %serviceModules) { if ((exists $serviceModuleObjects{$serviceModules{$smod}{"name"}}) && ($serviceModuleObjects{$serviceModules{$smod}{"name"}}->getState() == MOD_STATE_OK)) { eval { local $SIG{ALRM} = sub {die "alarm\n"}; alarm $serviceModules{$smod}{"timeout"}; $serviceModuleObjects{$serviceModules{$smod}{"name"}}->main(); alarm 0; }; # Check for alarm (timeout) condition if ($@) { printError("CORE", $serviceModules{$smod}{"name"}." Timed out:\n ".$@."\n"); } } } # sleep select undef, undef, undef, 0.1; } # loop end } #------------------------------------------------------------------------------# # Sub: daemonShutdown # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub daemonShutdown { printMessage("CORE", "Shutting down!\n"); # unload modules serviceModulesUnload(); # remove socket socketRemove(); # destroy db-bean printMessage("CORE", "shutting down FluxDB...\n"); if (defined($fluxDB)) { $fluxDB->destroy(); } # remove pid-file pidFileDelete(); # print that we started ok printMessage("CORE", "fluxd-shutdown complete.\n"); # get out here exit; } #------------------------------------------------------------------------------# # Sub: daemonIsRunning # # Arguments: docroot # # Returns: 0|1 # #------------------------------------------------------------------------------# sub daemonIsRunning { my $docroot = shift; if (!(defined $docroot)) { return 0; } my $qstring = "ps x -o pid='' -o ppid='' -o command='' -ww 2> /dev/null"; my $pcount = 0; foreach my $line (grep(/fluxd running.*$docroot/, qx($qstring))) { print STDOUT $line."\n"; $pcount++; } if ($pcount > 0) { return 1; } return 0; } #------------------------------------------------------------------------------# # Sub: initPaths # # Arguments: null # # Returns: Null # #------------------------------------------------------------------------------# sub initPaths { $path_transfer_dir = $path_path.$path_transfer_dir."/"; $path_data_dir = $path_path.$path_data_dir."/"; $path_socket = $path_data_dir.$path_socket; $log = $path_data_dir.$log; $log_error = $path_data_dir.$log_error; $file_pid = $path_data_dir.$file_pid; # check if our main-dir exists. try to create if it doesnt if (! -d $path_data_dir) { mkdir($path_data_dir, 0700); } } #------------------------------------------------------------------------------# # Sub: loadModules # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub loadModules { # print if ($loglevel > 1) { printMessage("CORE", "loading Perl-modules...\n"); } # load IO::Socket::UNIX if ($loglevel > 2) { printMessage("CORE", "loading Perl-module IO::Socket::UNIX\n"); } if (eval "require IO::Socket::UNIX") { IO::Socket::UNIX->import(); } else { printError("CORE", "load perl-module IO::Socket::UNIX failed\n"); exit; } # load IO::Select if ($loglevel > 2) { printMessage("CORE", "loading Perl-module IO::Select\n"); } if (eval "require IO::Select") { IO::Select->import(); } else { printError("CORE", "load perl-module IO::Select failed\n"); exit; } # load POSIX if ($loglevel > 2) { printMessage("CORE", "loading Perl-module POSIX\n"); } if (eval "require POSIX") { POSIX->import(qw(setsid)); } else { printError("CORE", "load perl-module POSIX failed\n"); exit; } # print if ($loglevel > 1) { printMessage("CORE", "Perl-modules loaded.\n"); } } #------------------------------------------------------------------------------# # Sub: serviceModuleLoad # # Arguments: name of module # # Returns: 0|1 # #------------------------------------------------------------------------------# sub serviceModuleLoad { my $modName = shift; if (exists $serviceModuleObjects{$modName}) { return 1; } if ($loglevel > 1) { printMessage("CORE", "loading service-module ".$modName." ...\n"); } # create and initialize if (eval "require ".$modName) { eval { $serviceModuleObjects{$modName} = eval $modName."->new();"; $serviceModuleObjects{$modName}->initialize(); if ($serviceModuleObjects{$modName}->getState() != MOD_STATE_OK) { my $msg = "error initializing service-module ".$modName." :\n"; $msg .= " ".$serviceModuleObjects{$modName}->getMessage()."\n"; printError("CORE", $msg); } }; if ($@) { printError("CORE", "error loading service-module ".$modName." : ".$@."\n"); } else { # everything ok if ($loglevel > 0) { printMessage("CORE", $modName." loaded\n"); } return 1; } } else { printError("CORE", "error loading service-module ".$modName." : ".$@."\n"); } } #------------------------------------------------------------------------------# # Sub: serviceModuleUnload # # Arguments: name of module # # Returns: 0|1 # #------------------------------------------------------------------------------# sub serviceModuleUnload { my $modName = shift; if (exists $serviceModuleObjects{$modName}) { if ($loglevel > 1) { printMessage("CORE", "unloading service-module ".$modName." ...\n"); } eval { $serviceModuleObjects{$modName}->destroy(); delete($serviceModuleObjects{$modName}); }; if ($@) { printError("CORE", "error unloading service-module ".$modName." : ".$@."\n"); return 0; } else { # everything ok if ($loglevel > 0) { printMessage("CORE", $modName." unloaded\n"); } } } return 1; } #------------------------------------------------------------------------------# # Sub: serviceModulesLoad # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub serviceModulesLoad { # print if ($loglevel > 0) { printMessage("CORE", "loading service-modules...\n"); } # load/unload foreach my $smod (sort keys %serviceModules) { if (FluxDB->getFluxConfig("fluxd_".$serviceModules{$smod}{"name"}."_enabled") == 1) { # Load up module, unless it is already serviceModuleLoad($serviceModules{$smod}{"name"}); } else { # Unload module, if it is loaded serviceModuleUnload($serviceModules{$smod}{"name"}); } } # set command line my @cmdmodlist = (); foreach my $smod (sort keys %serviceModules) { if ((exists $serviceModuleObjects{$serviceModules{$smod}{"name"}}) && ($serviceModuleObjects{$serviceModules{$smod}{"name"}}->getState() == MOD_STATE_OK)) { push(@cmdmodlist, $serviceModules{$smod}{"name"}); } } my $cmdmodliststr = (scalar(@cmdmodlist) > 0) ? join(" ", @cmdmodlist) : "No service-modules loaded"; $0 = '[ fluxd running ('.$path_docroot.') ('.$cmdmodliststr.') ]'; # print if ($loglevel > 0) { printMessage("CORE", "done loading service-modules.\n"); } } #------------------------------------------------------------------------------# # Sub: serviceModulesUnload # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub serviceModulesUnload { # print if ($loglevel > 0) { printMessage("CORE", "unloading service-modules...\n"); } # unload foreach my $smod (sort keys %serviceModules) { serviceModuleUnload($serviceModules{$smod}{"name"}); } # print if ($loglevel > 0) { printMessage("CORE", "done unloading service-modules.\n"); } } #------------------------------------------------------------------------------# # Sub: serviceModuleList # # Arguments: null # # Returns: string with list of mods+state # #------------------------------------------------------------------------------# sub serviceModuleList { # retval my $modList = ""; # build list foreach my $smod (sort keys %serviceModules) { $modList .= $serviceModules{$smod}{"name"}.$delimState; if (exists $serviceModuleObjects{$serviceModules{$smod}{"name"}}) { $modList .= $serviceModuleObjects{$serviceModules{$smod}{"name"}}->getState(); } else { $modList .= MOD_STATE_NULL; } $modList .= $delimMod; } # return return (substr ($modList, 0, (length($modList)) - 1)); } #------------------------------------------------------------------------------# # Sub: serviceModuleState # # Arguments: name of service-module # # Returns: state of service-module # #------------------------------------------------------------------------------# sub serviceModuleState { my $modName = shift; if (exists $serviceModuleObjects{$modName}) { return $serviceModuleObjects{$modName}->getState(); } else { return MOD_STATE_NULL; } } #------------------------------------------------------------------------------# # Sub: gotSigHup # # Arguments: Null # # Returns: Null # #------------------------------------------------------------------------------# sub gotSigHup { printMessage("CORE", "got SIGHUP, reloading config and service-modules...\n"); # have FluxDB reload the DB first, so we can see the changes if ($fluxDB->reload()) { serviceModulesLoad(); } else { my $msg = "Error connecting to DB to read changes :\n"; $msg .= $fluxDB->getMessage()."\n"; printError("CORE", $msg); } } #------------------------------------------------------------------------------# # Sub: gotSigInt # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub gotSigInt { printMessage("CORE", "got SIGINT, setting shutdown-flag...\n"); # set main-loop-flag $loop = 0; } #------------------------------------------------------------------------------# # Sub: gotSigTerm # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub gotSigTerm { printMessage("CORE", "got SIGTERM, setting shutdown-flag...\n"); # set main-loop-flag $loop = 0; } #------------------------------------------------------------------------------# # Sub: gotSigQuit # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub gotSigQuit { printMessage("CORE", "got SIGQUIT, setting shutdown-flag...\n"); # set main-loop-flag $loop = 0; } #------------------------------------------------------------------------------# # Sub: checkConnections # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub checkConnections { # Get the readable handles. timeout is 0, only process stuff that can be # read NOW. my $return = ""; my @ready = $select->can_read(0); foreach my $socket (@ready) { if ($socket == $server) { my $new = $socket->accept(); $select->add($new); } else { my $buf = ""; my $char = getc($socket); while ((defined($char)) && ($char ne "\n")) { $buf .= $char; $char = getc($socket); } $return = processRequest($buf); $socket->send($return,0,$socket); $select->remove($socket); close($socket); } } } #------------------------------------------------------------------------------# # Sub: processRequest # # Arguments: Command # # Returns: String info on command success/failure # #------------------------------------------------------------------------------# sub processRequest { my @array = (); my $temp = shift; @array = split (/ /, $temp); @_ = @array; my $return; SWITCH: { $_ = shift; # Actual fluxd subroutine calls /^modlist/ && do { $return = serviceModuleList(); last SWITCH; }; /^modstate/ && do { $return = serviceModuleState(shift); last SWITCH; }; /^status/ && do { $return = status(); last SWITCH; }; /^set/ && do { $return = set(shift, shift); last SWITCH; }; /^reloadDBCache/ && do { $return = $fluxDB->reload(); last SWITCH; }; /^reloadModules/ && do { $return = serviceModulesLoad(); last SWITCH; }; /^check/ && do { $return = check(); last SWITCH; }; /^die/ && do { # set main-loop-flag $loop = 0; $return = 1; last SWITCH; }; # module-calls /^!(.+):(.+)/ && do { my $mod = $1; my $command = $2; $return = ""; if (exists $serviceModuleNames{$mod}) { if ((exists $serviceModuleObjects{$mod}) && ($serviceModuleObjects{$mod}->getState() == MOD_STATE_OK)) { $return = $serviceModuleObjects{$mod}->command($command); } } else { $return = "Unknown Module"; } last SWITCH; }; # Default case. $return = printUsage(1); } # return return $return; } #------------------------------------------------------------------------------# # Sub: set # # Arguments: Variable, [Value] # # Returns: null # #------------------------------------------------------------------------------# sub set { my $variable = shift; my $value = shift; my $return; if ($variable =~/::/) { # setting/getting package variable my @pair = split(/::/, $variable); if (exists $serviceModuleNames{$pair[0]}) { if ((exists $serviceModuleObjects{$pair[0]}) && ($serviceModuleObjects{$pair[0]}->getState() == MOD_STATE_OK)) { $return = $serviceModuleObjects{$pair[0]}->set($pair[1], $value); } } else { $return = "Unknown Module"; } } return $return; } #------------------------------------------------------------------------------# # Sub: fluxcli # # Arguments: Command[, Args] # # Returns: string or 0|1 # #------------------------------------------------------------------------------# sub fluxcli { my ($Command, @Args) = @_; my $Args = $#Args + 1; my ($ArgsReq, $ArgsMax); # qx for ($Command) { if (/^transfers|^netstat/) { $ArgsReq = 0; last; } if (/^dump/) { $ArgsReq = 1; last; } } if (defined $ArgsReq) { return printUsage() if ($Args < $ArgsReq || $Args > (defined $ArgsMax ? $ArgsMax : $ArgsReq)); my $shellCmd = $bin_php." bin/".$bin_fluxcli." ".quotemeta($Command).appendArgs(\@Args, $ArgsReq)." 2>> ".$log_error; return qx($shellCmd); } # syscall for ($Command) { if (/^start-all|^resume-all/) { $ArgsReq = 0; $ArgsMax = 2; last; } if (/^stop-all|^repair/) { $ArgsReq = 0; last; } if (/^start/) { $ArgsReq = 1; $ArgsMax = 3; last; } if (/^stop|^reset|^delete|^wipe|^xfer/) { $ArgsReq = 1; last; } if (/^inject|^watch/) { $ArgsReq = 2; $ArgsMax = 4; last; } if (/^maintenance/) { $ArgsReq = 0; $ArgsMax = 1; last; } if (/^rss/) { $ArgsReq = 4; $ArgsMax = 5; last; } } if (defined $ArgsReq) { return 0 if ($Args < $ArgsReq || $Args > (defined $ArgsMax ? $ArgsMax : $ArgsReq)); my $shellCmd = $bin_php." bin/".$bin_fluxcli." ".quotemeta($Command).appendArgs(\@Args, $ArgsReq); return doSysCall($shellCmd); } } #------------------------------------------------------------------------------# # Sub: appendArgs # # Arguments: RefArgs[, ArgsReq] # # Returns: Command-string fragment # #------------------------------------------------------------------------------# sub appendArgs { my $Args = shift; my $ArgsReq = shift; $ArgsReq = 0 if (!defined $ArgsReq); # Iterate from last-to-first, to skip missing # rightmost non-mandatory args. my $return = ''; my $canSkip = 1; for (my $i = ($ArgsReq > $#$Args ? $ArgsReq - 1 : $#$Args); $i >= 0; $i--) { my $Arg = $$Args[$i]; my $ArgPresent = defined $Arg; $canSkip = 0 if ($canSkip && ($i < $ArgsReq || $ArgPresent)); if ($canSkip && !$ArgPresent) { } elsif (!$ArgPresent || length($Arg) == 0) { $return = " ''".$return; } else { $return = ' '.quotemeta($Arg).$return; } } return $return; } #------------------------------------------------------------------------------# # Sub: doSysCall # # Arguments: Command-string # # Returns: 0|1 # #------------------------------------------------------------------------------# sub doSysCall { my $command = shift; $command .= " 1>> ".$log." 2>> ".$log_error." &"; system($command); if ($? == -1) { printError("CORE", "failed to execute: ".$!."; command:\n".$command."\n"); } elsif ($? & 127) { printError("CORE", (sprintf "child died with signal %d, %s coredump; command:\n%s\n", ($? & 127), ($? & 128) ? 'with' : 'without'), $command); } else { if ($loglevel > 2) { printMessage("CORE", (sprintf "child exited with value %d; command:\n%s\n", $? >> 8, $command)); } return 1; } return 0; } #------------------------------------------------------------------------------# # Sub: lrtrim # # Arguments: string # # Returns: trimmed and chomped string # #------------------------------------------------------------------------------# sub lrtrim($) { $_ = shift; chomp; s/^\s+//; s/\s+$//; return $_; } #------------------------------------------------------------------------------# # Sub: socketInitialize # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub socketInitialize { $server = IO::Socket::UNIX->new( Type => IO::Socket::UNIX->SOCK_STREAM, Local => $path_socket, Listen => 16, Reuse => 1, ); # check socket unless ($server) { printError("CORE", "could not create socket: ".$!."\n"); exit; } # print if ($loglevel > 0) { printMessage("CORE", "created socket ".$path_socket."\n"); } # create select $select = new IO::Select(); # Add our server socket to the select read set. $select->add($server); } #------------------------------------------------------------------------------# # Sub: socketRemove # # Arguments: null # # Returns: null # #------------------------------------------------------------------------------# sub socketRemove { if ($loglevel > 0) { printMessage("CORE", "removing socket ".$path_socket."\n"); } unlink($path_socket); } #------------------------------------------------------------------------------# # Sub: pidFileWrite # # Arguments: int with pid # # Returns: null # #------------------------------------------------------------------------------# sub pidFileWrite { my $pid = shift; if (!(defined $pid)) { $pid = $$; } if ($loglevel > 0) { printMessage("CORE", "writing pid-file ".$file_pid." (pid: ".$pid.")\n"); } open(PIDFILE,">$file_pid"); print PIDFILE $pid."\n"; close(PIDFILE); } #------------------------------------------------------------------------------# # Sub: pidFileDelete # # Arguments: null # # Returns: return-val of delete # #------------------------------------------------------------------------------# sub pidFileDelete { if ($loglevel > 0) { printMessage("CORE", "deleting pid-file ".$file_pid."\n"); } return unlink($file_pid); } #------------------------------------------------------------------------------# # Sub: status # # Arguments: Null # # Returns: Server information page # #------------------------------------------------------------------------------# sub status { my $head = ""; $head .= "\n\nfluxd has been up since ".$start_time_local." (".FluxCommon::niceTimeString($start_time).")\n\n"; $head .= "data-dir : ".$path_data_dir."\n"; $head .= "log : ".$log."\n"; $head .= "error-log : ".$log_error."\n"; $head .= "pid : ".$file_pid."\n"; $head .= "socket : ".$path_socket."\n"; $head .= "transfers-dir : ".$path_transfer_dir."\n"; $head .= "docroot : ".$path_docroot."\n"; $head .= "fluxcli : ".$path_docroot."bin/".$bin_fluxcli."\n"; $head .= "php : ".$bin_php."\n"; $head .= "db-mode : ".$dbMode."\n"; $head .= "loglevel : ".$loglevel."\n"; $head .= "\n"; my $status = ""; my $modules = "- Loaded Modules -\n"; foreach my $smod (sort keys %serviceModules) { if ((exists $serviceModuleObjects{$serviceModules{$smod}{"name"}}) && ($serviceModuleObjects{$serviceModules{$smod}{"name"}}->getState() == MOD_STATE_OK)) { $modules .= " * ".$serviceModules{$smod}{"name"}."\n"; $status .= eval { $serviceModuleObjects{$serviceModules{$smod}{"name"}}->status(); }; } } # return return $head.$modules.$status; } #------------------------------------------------------------------------------# # Sub: printVersion # # Arguments: Null # # Returns: Version Information # #------------------------------------------------------------------------------# sub printVersion { print $PROG.".".$EXTENSION." Version ".$VERSION."\n"; # FluxCommon print "FluxCommon Version : "; print FluxCommon::getVersion()."\n"; # StatFile print "StatFile Version : "; print StatFile::getVersion()."\n"; # FluxDB print "FluxDB Version : "; if (eval "require FluxDB") { print FluxDB->getVersion()."\n"; } else { print "cant load module\n"; } # service-mods foreach my $smod (sort keys %serviceModules) { print $serviceModules{$smod}{"name"}." Version : "; if (eval "require ".$serviceModules{$smod}{"name"}) { my $modversion = eval $serviceModules{$smod}{"name"}."->getVersion();"; print $modversion."\n"; } else { print "cant load module\n"; } } } #------------------------------------------------------------------------------# # Sub: check # # Arguments: Null # # Returns: info on sys requirements # #------------------------------------------------------------------------------# sub check { my $errors = 0; my $warnings = 0; my @errorMessages = (); my @warningMessages = (); printMessage("CORE", "checking requirements...\n"); # 1. CORE-Perl-modules printMessage("CORE", "1. CORE-Perl-modules\n"); my @mods = ('IO::Select', 'IO::Socket::UNIX', 'IO::Socket::INET', 'POSIX'); foreach my $mod (@mods) { if (eval "require $mod") { printMessage("CORE", " - OK : ".$mod."\n"); next; } else { $errors++; push(@errorMessages, "Loading of CORE-Perl-module ".$mod." failed.\n"); printMessage("CORE", " - FAILED : ".$mod."\n"); } } # 2. FluxDB-Perl-modules printMessage("CORE", "2. Database-Perl-modules\n"); if (eval "require DBI") { printMessage("CORE", " - OK : DBI\n"); } else { $warnings++; push(@warningMessages, "Loading of FluxDB-Perl-module DBI failed. fluxd cannot work in DBI/DBD-mode but only in PHP-mode.\n"); printMessage("CORE", " - FAILED : DBI\n"); } my $dbdwarnings = 0; @mods = ('DBD::mysql', 'DBD::SQLite', 'DBD::Pg'); foreach my $mod (@mods) { if (eval "require $mod") { printMessage("CORE", " - OK : ".$mod."\n"); next; } else { $dbdwarnings++; printMessage("CORE", " - FAILED : ".$mod."\n"); } } if ($dbdwarnings == 3) { $warnings++; push(@warningMessages, "No DBD-Module could be loaded. fluxd cannot work in DBI/DBD-mode but only in PHP-mode.\n"); } # 3. Result printMessage("CORE", "3. Result : ".(($errors == 0) ? "PASSED" : "FAILED")."\n"); # failures if ($errors > 0) { printMessage("CORE", "Errors:\n"); foreach my $msg (@errorMessages) { printMessage("CORE", $msg); } } # warnings if ($warnings > 0) { printMessage("CORE", "Warnings:\n"); foreach my $msg (@warningMessages) { printMessage("CORE", $msg); } } } #------------------------------------------------------------------------------# # Sub: debug # # Arguments: Null # # Returns: Null # #------------------------------------------------------------------------------# sub debug { my $debug = shift @ARGV; # first arg is debug-operation. if (!(defined $debug)) { printMessage("CORE", "debug is missing an operation.\n"); exit; } # database-debug if ($debug =~ /db/) { # $path_docroot my $temp = shift @ARGV; if (!(defined $temp)) { printMessage("CORE", "debug database is missing an argument : path to docroot\n"); exit; } if (!((substr $temp, -1) eq "/")) { $temp .= "/"; } $path_docroot = $temp; # PATH_PATH $temp = shift @ARGV; if (!(defined $temp)) { printMessage("CORE", "debug database is missing an argument : path to path\n"); exit; } if (!((substr $temp, -1) eq "/")) { $temp .= "/"; } $path_path = $temp; # $bin_php $temp = shift @ARGV; if (!(defined $temp)) { printMessage("CORE", "debug database is missing an argument : path to php\n"); exit; } $bin_php = $temp; printMessage("CORE", "debugging database...\n"); # require require FluxDB; # create instance printMessage("CORE", "creating \$fluxDB\n"); $fluxDB = FluxDB->new(); # PHP # initialize printMessage("CORE", "initializing \$fluxDB (php)\n"); $fluxDB->initialize($path_docroot, $bin_php, "php"); if ($fluxDB->getState() != MOD_STATE_OK) { printMessage("CORE", "error : ".$fluxDB->getMessage()."\n"); exit; } # something from the bean printMessage("CORE", "FluxConfig(\"path\") : \"".FluxDB->getFluxConfig("path")."\"\n"); printMessage("CORE", "FluxConfig(\"docroot\") : \"".FluxDB->getFluxConfig("docroot")."\"\n"); # test to set a val printMessage("CORE", "FluxConfig(\"default_theme\") : \"".FluxDB->getFluxConfig("default_theme")."\"\n"); $fluxDB->setFluxConfig("default_theme","foo"); printMessage("CORE", "FluxConfig(\"default_theme\") after set : \"".FluxDB->getFluxConfig("default_theme")."\"\n"); # now reload and check again $fluxDB->reload(); printMessage("CORE", "FluxConfig(\"default_theme\") after reload : \"".FluxDB->getFluxConfig("default_theme")."\"\n"); # destroy printMessage("CORE", "destroying \$fluxDB\n"); $fluxDB->destroy(); # DBI # initialize printMessage("CORE", "initializing \$fluxDB (dbi)\n"); $fluxDB->initialize($path_docroot, $bin_php, "dbi"); if ($fluxDB->getState() != MOD_STATE_OK) { printMessage("CORE", "error : ".$fluxDB->getMessage()."\n"); # db-settings printMessage("CORE", " DatabaseType : \"".$fluxDB->getDatabaseType()."\"\n"); printMessage("CORE", " DatabaseName : \"".$fluxDB->getDatabaseName()."\"\n"); printMessage("CORE", " DatabaseHost : \"".$fluxDB->getDatabaseHost()."\"\n"); printMessage("CORE", " DatabasePort : \"".$fluxDB->getDatabasePort()."\"\n"); printMessage("CORE", " DatabaseUser : \"".$fluxDB->getDatabaseUser()."\"\n"); printMessage("CORE", " DatabasePassword : \"".$fluxDB->getDatabasePassword()."\"\n"); printMessage("CORE", " DatabaseDSN : \"".$fluxDB->getDatabaseDSN()."\"\n"); exit; } # db-settings printMessage("CORE", "DatabaseDSN : \"".$fluxDB->getDatabaseDSN()."\"\n"); # something from the bean printMessage("CORE", "FluxConfig(\"path\") : \"".FluxDB->getFluxConfig("path")."\"\n"); printMessage("CORE", "FluxConfig(\"docroot\") : \"".FluxDB->getFluxConfig("docroot")."\"\n"); # test to set a val printMessage("CORE", "FluxConfig(\"default_theme\") : \"".FluxDB->getFluxConfig("default_theme")."\"\n"); $fluxDB->setFluxConfig("default_theme","foo"); printMessage("CORE", "FluxConfig(\"default_theme\") after set : \"".FluxDB->getFluxConfig("default_theme")."\"\n"); # now reload and check again $fluxDB->reload(); printMessage("CORE", "FluxConfig(\"default_theme\") after reload : \"".FluxDB->getFluxConfig("default_theme")."\"\n"); # destroy printMessage("CORE", "destroying \$fluxDB\n"); $fluxDB->destroy(); # done printMessage("CORE", "database debug done.\n"); exit; } # bail out printMessage("CORE", "debug is missing an operation.\n"); exit; } #------------------------------------------------------------------------------# # Sub: getLoglevel # # Arguments: null # # Returns: loglevel-int # #------------------------------------------------------------------------------# sub getLoglevel { return $loglevel; } #------------------------------------------------------------------------------# # Sub: getPathDataDir # # Arguments: null # # Returns: path-string # #------------------------------------------------------------------------------# sub getPathDataDir { return $path_data_dir; } #------------------------------------------------------------------------------# # Sub: getPathTransferDir # # Arguments: null # # Returns: path-string # #------------------------------------------------------------------------------# sub getPathTransferDir { return $path_transfer_dir; } #------------------------------------------------------------------------------# # Sub: printMessage # # Arguments: module, message # # Return: null # #------------------------------------------------------------------------------# sub printMessage { my $module = shift; my $message = shift; print STDOUT FluxCommon::getTimeStamp()."[".$module."] ".$message; } #------------------------------------------------------------------------------# # Sub: printError # # Arguments: module, message # # Return: null # #------------------------------------------------------------------------------# sub printError { my $module = shift; my $message = shift; print STDERR FluxCommon::getTimeStamp()."[".$module."] ".$message; } #------------------------------------------------------------------------------# # Sub: logMessage # # Arguments: module, message # # Return: null # #------------------------------------------------------------------------------# sub logMessage { my $module = shift; my $message = shift; logToFile($log, FluxCommon::getTimeStamp()."[".$module."] ".$message); } #------------------------------------------------------------------------------# # Sub: logError # # Arguments: module, message # # Return: null # #------------------------------------------------------------------------------# sub logError { my $module = shift; my $message = shift; logToFile($log_error, FluxCommon::getTimeStamp()."[".$module."] ".$message); } #------------------------------------------------------------------------------# # Sub: logToFile # # Arguments: file, message # # Return: null # #------------------------------------------------------------------------------# sub logToFile { my $file = shift; my $message = shift; open(LOG, ">>$file"); print LOG $message; close LOG; } #------------------------------------------------------------------------------# # Sub: printUsage # # Arguments: bool (or undefined) # # Returns: Usage Information # #------------------------------------------------------------------------------# sub printUsage { my $return = shift; my $data = <<"USAGE"; $PROG.$EXTENSION Revision $VERSION Usage: $PROG.$EXTENSION path-to-docroot path-to-path path-to-php db-mode start fluxd daemon. db-mode : dbi/php $PROG.$EXTENSION path-to-docroot path-to-path path-to-php db-mode stop fluxd daemon db-mode : dbi/php $PROG.$EXTENSION check for requirements. $PROG.$EXTENSION type path-to-docroot path-to-path path-to-php debug fluxd daemon type : db $PROG.$EXTENSION <-v|--version> print out version-info $PROG.$EXTENSION <-h|--help> print out help screen. USAGE if ($return) { return $data; } else { print $data; } }