background handling polish
authorTony Cook <tony@develop-help.com>
Wed, 4 Nov 2009 03:33:01 +0000 (03:33 +0000)
committertony <tony@45cb6cf1-00bc-42d2-bb5a-07f51df49f94>
Wed, 4 Nov 2009 03:33:01 +0000 (03:33 +0000)
site/cgi-bin/modules/BSE/NotifyFiles.pm
site/cgi-bin/modules/BSE/TB/BackgroundTask.pm
site/cgi-bin/modules/BSE/UI/Background.pm
site/data/db/bse_background_tasks.data
site/htdocs/css/admin.css
site/templates/admin/back/detail.tmpl
site/templates/admin/back/list.tmpl
site/util/bse_back.pl
site/util/bse_notify_files.pl
site/util/bse_storage.pl

index 4b0b46e..c6b2a55 100644 (file)
@@ -37,8 +37,8 @@ sub expand_groups {
   my ($self) = @_;
 
   $self->lock
-    or die "Cannot acquire notify_files lock\n"
-;
+    or die "Cannot acquire notify_files lock\n";
+
   $self->_clear_obsolete;
 
   $self->_expand_groups;
@@ -49,6 +49,8 @@ sub expand_groups {
 sub _clear_obsolete {
   my ($self) = @_;
 
+  $self->_progress("Clearing obsolete notifcations");
+
   my $max_age = $self->{cfg}->entry("notify files", "oldest_notify", 7);
   BSE::DB->run(bseClearOldFileNotifications => $max_age);
 }
@@ -56,6 +58,8 @@ sub _clear_obsolete {
 sub _expand_groups {
   my ($self) = @_;
 
+  $self->_progress("Expanding group notificatioons");
+
   # a few at a time
   while (my @group_entries = BSE::DB->query("bseNotifyFileGroupEntries")) {
     for my $group_entry (@group_entries) {
@@ -86,6 +90,8 @@ sub _expand_group {
 sub _send_messages {
   my ($self) = @_;
 
+  $self->_progress("Sending emails");
+
   my @user_ids = map $_->{id}, BSE::DB->query("bseFileNotifyUsers");
   for my $user_id (@user_ids) {
     $self->_notify_user($user_id);
@@ -110,6 +116,8 @@ sub _notify_user {
 sub _notify_user_low {
   my ($self, $user_id, $user, $orig_entries) = @_;
 
+  $self->_detail("Emailing: ", $user->userId);
+
   # we keep the original entry list, since we want to delete them all
   # at the end, but we don't want to delete entries added after we
   # started processing the user.
@@ -196,4 +204,18 @@ sub testlock {
   return !$row->[0];
 }
 
+sub _progress {
+  my ($self, @text) = @_;
+
+  $self->{verbose} && $self->{output}
+    and $self->{output}->(@text);
+}
+
+sub _detail {
+  my ($self, @text) = @_;
+
+  $self->{verbose} > 1 && $self->{output}
+    and $self->{output}->(@text);
+}
+
 1;
index 3978f3a..3419a25 100644 (file)
@@ -49,6 +49,7 @@ sub start {
 
   my $cfg = delete $opts{cfg};
   my $msg = delete $opts{msg};
+  my $foreground = delete $opts{foreground};
 
   # find the binary
   my $binname = $self->binname;
@@ -85,66 +86,71 @@ sub start {
     return;
   }
   
-  my $pid = fork;
-  unless (defined $pid) {
-    $$msg = "Could not fork: $!";
-    return;
-  }
   my $task_id = $self->id;
-  if ($pid) {
-    # parent process
-    $self->set_task_pid($pid);
-    $self->set_running(1);
-    $self->set_last_started(now_sqldatetime());
-    $self->save;
 
-    return $pid;
-  }
-  else {
+  unless ($foreground) {
+    my $pid = fork;
+    unless (defined $pid) {
+      $$msg = "Could not fork: $!";
+      return;
+    }
+
+    if ($pid) {
+      # parent
+      return $pid;
+    }
+
+    # child
     BSE::DB->forked;
+  }
 
-    # child process
-    my $null = $^O eq 'MSWin32' ? "NUL" : "/dev/null";
-    untie *STDIN;
-    open STDIN, "<$null" 
-      or die "Cannot open $null: $!";
-    untie *STDOUT;
-    open STDOUT, ">&".fileno($outfh)
-      or die "Cannot redirect stdout: $!";
-    untie *STDERR;
-    open STDERR, ">&STDOUT" or die "Cannot redirect STDOUT: $!";
+  # child process
+  my $null = $^O eq 'MSWin32' ? "NUL" : "/dev/null";
+  untie *STDIN;
+  open STDIN, "<$null" 
+    or die "Cannot open $null: $!";
+  untie *STDOUT;
+  open STDOUT, ">&".fileno($outfh)
+    or die "Cannot redirect stdout: $!";
+  untie *STDERR;
+  open STDERR, ">&STDOUT" or die "Cannot redirect STDOUT: $!";
     POSIX::setsid();
 
-    my $pid2 = fork;
-    unless (defined $pid) {
-      print STDERR "Cannot start second child: $!\n";
-      $self->set_running(0);
-      $self->set_task_pid(undef);
-      $self->save;
-      exit;
-    }
-
-    if ($pid2) {
-      waitpid $pid2, 0;
-      if ($?) {
-       print STDERR "Task exited with non-zero-status: $?\n";
-      }
-      # this can happen hours or minutes after the original task changes
-      # and it's in a different process too
-      my $task = BSE::TB::BackgroundTasks->getByPkey($task_id);
-      $task->set_running(0);
-      $task->set_task_pid(undef);
-      $task->set_last_exit($?);
-      $task->set_last_completion(now_sqldatetime());
-      $task->save;
-      exit;
+  my $pid2 = fork;
+  unless (defined $pid2) {
+    print STDERR "Cannot start second child: $!\n";
+    $self->set_running(0);
+    $self->set_task_pid(undef);
+    $self->save;
+    exit;
+  }
+  
+  if ($pid2) {
+    # the working child pid is more interesting
+    $self->set_task_pid($pid2);
+    $self->set_running(1);
+    $self->set_last_started(now_sqldatetime());
+    $self->save;
+    
+    waitpid $pid2, 0;
+    if ($?) {
+      print STDERR "Task exited with non-zero-status: $?\n";
     }
-    else {
-      BSE::DB->forked;
-      {  exec $binname, @args; } # suppress warning
+    # this can happen hours or minutes after the original task changes
+    # and it's in a different process too
+    my $task = BSE::TB::BackgroundTasks->getByPkey($task_id);
+    $task->set_running(0);
+    $task->set_task_pid(undef);
+    $task->set_last_exit($?);
+    $task->set_last_completion(now_sqldatetime());
+    $task->save;
+    exit;
+  }
+  else {
+    BSE::DB->forked;
+    {  exec $binname, @args; } # suppress warning
       print STDERR "Exec of $binname failed: $!\n";
-      exit 1;
-    }
+    exit 1;
   }
 }
 
index e4d9a6e..7a6f8d5 100644 (file)
@@ -8,6 +8,7 @@ use BSE::Util::SQL qw(now_sqldatetime);
 use DevHelp::HTML;
 use IO::File;
 use BSE::Util::Tags qw(tag_hash);
+use Config;
 
 my %actions =
   (
@@ -23,6 +24,15 @@ sub rights { \%actions }
 
 sub default_action { "list" }
 
+my %signames;
+if ($Config{sig_name} && $Config{sig_num}) {
+  my @names = split ' ', $Config{sig_name};
+  my @nums = split ' ', $Config{sig_num};
+  for my $i (0 .. $#names) {
+    $signames{$nums[$i]} ||= $names[$i];
+  }
+}
+
 sub req_list {
   my ($self, $req, $errors) = @_;
 
@@ -44,6 +54,8 @@ sub req_list {
      ),
      message => $message,
      task_running => [ tag_task_running => $self, \$current_task ],
+     task_exit => [ tag_task_exit => $self, \$current_task ],
+     task_signal => [ tag_task_signal => $self, \$current_task ],
     );
 
   return $req->dyn_response("admin/back/list", \%acts);
@@ -57,6 +69,22 @@ sub tag_task_running {
   return $$rcurrent->check_running;
 }
 
+sub tag_task_exit {
+  my ($self, $rcurrent) = @_;
+
+  $$rcurrent or return '';
+
+  return $$rcurrent->last_exit() >> 8;
+}
+
+sub tag_task_signal {
+  my ($self, $rcurrent) = @_;
+
+  $$rcurrent or return '';
+
+  return $$rcurrent->last_exit() & 127;
+}
+
 sub _get_task {
   my ($req, $msg) = @_;
 
@@ -114,6 +142,8 @@ sub req_detail {
       $logtext = <$fh>;
     }
   }
+  my $signum = (($task->last_exit() || 0) & 127);
+  my $signame = $signames{$signum} || '';
   my %acts =
     (
      BSE::Util::Tags->basic(undef, $req->cgi, $req->cfg),
@@ -121,6 +151,9 @@ sub req_detail {
      BSE::Util::Tags->admin(undef, $req->cfg),
      task => [ \&tag_hash, $task ],
      task_running => scalar($task->check_running),
+     task_exit => scalar(($task->last_exit() || 0) >> 8),
+     task_signal => $signum,
+     task_signal_name => $signame,
      log => escape_html($logtext),
     );
 
index 5293489..ea206eb 100644 (file)
@@ -1,7 +1,17 @@
 --
-id: gen
+id: bse_gen
 description: Regenerate Site
 binname: perl util/gen.pl
 bin_opts: -v
 start_right: regen_all
 
+id: bse_sync_storage
+description: Synchronize File Stores
+binname: perl util/bse_storage.pl
+bin_opts: sync -v
+
+id: bse_notify_files
+description: Notify Members about new files
+binname: perl util/bse_notify_files.pl
+bin_opts: -v 2
+
index 377b119..686628c 100644 (file)
@@ -205,4 +205,12 @@ div.menu {
 #fileaccesslog a:visited,
 #fileaccesslog a:active { 
   font-weight: normal;
-}
\ No newline at end of file
+}
+
+table#backtasklist tr.running td { 
+  background-color: #E0E0FF;
+}
+
+table#backtasklist tr.failed td { 
+  background-color: #FFE0E0;
+}
index cd8d6c2..dbbdea7 100644 (file)
   <th>Status</th>
   <td><:ifTask_running:>Running (<:task task_pid:>)<:or:>Stopped<:eif:></td>
 </tr>
+<tr>
+  <th>Completion Status:</th>
+  <td><:if Eq [task last_exit] 0:>Success
+<:or Eq:>
+Failed
+<:switch:>
+<:case task_exit:>(Exit: <:task_exit:>)
+<:case task_signal:>(Signal: <:task_signal_name:>)
+<:case default:>(Unknown cause)
+<:endswitch:>
+<:eif Eq:>
+</tr>
 <tr>
   <th>Last Started</th>
   <td><:task last_started:></td>
index d882b19..b760e36 100644 (file)
@@ -1,6 +1,6 @@
 <:wrap admin/xbase.tmpl title=>"Background tasks", showtitle => 1 :>
 <:ifMessage:><p><:message:></p><:or:><:eif:>
-<table class="editform">
+<table class="editform" id="backtasklist">
 <tr>
   <th>Task</th>
   <th>Status</th>
@@ -11,9 +11,9 @@
 </tr>
 <:if Tasks:>
 <:iterator begin tasks:>
-<tr>
+<tr <:switch:><:case task_running:>class="running"<:case task last_exit:>class="failed"<:endswitch:>>
   <td><:task description:></td>
-  <td><:ifTask running:>Running (<:task task_pid:>)<:or:>Stopped<:eif:></td>
+  <td><:ifTask_running:>Running (<:task task_pid:>)<:or:>Stopped<:eif:></td>
   <td><:task last_started:></td>
   <td><:task last_completion:></td>
   <td><:switch:><:case Eq [task last_exit] "":><:case task last_exit:>Failed<:case default:>Success<:endswitch:></td>
index 07d4f9d..e9bcbaa 100644 (file)
@@ -5,6 +5,7 @@ use FindBin;
 use lib "$FindBin::Bin/../cgi-bin/modules";
 use BSE::Cfg;
 use BSE::TB::BackgroundTasks;
+use Getopt::Long;
 
 {
   chdir "$FindBin::Bin/../cgi-bin"
@@ -16,7 +17,10 @@ use BSE::TB::BackgroundTasks;
     or usage();
 
   if ($cmd eq "start") {
-    do_start(\@ARGV, $cfg);
+    do_start(\@ARGV, $cfg, $cmd, 0);
+  }
+  elsif ($cmd eq "run") {
+    do_start(\@ARGV, $cfg, $cmd, 1);
   }
   elsif ($cmd eq "status") {
     do_status(\@ARGV, $cfg);
@@ -38,17 +42,17 @@ sub _get_task {
   my ($args, $cmd) = @_;
 
   my $task_id = shift @$args
-    or usage("start missing taskid parameter");
+    or usage("$cmd: missing taskid parameter");
   my $task = BSE::TB::BackgroundTasks->getByPkey($task_id)
-    or usage("Unknown taskid");
+    or usage("$cmd: Unknown taskid '$task_id'");
 
   return $task;
 }
 
 sub do_start {
-  my ($args, $cfg) = @_;
+  my ($args, $cfg, $cmd, $foreground) = @_;
 
-  my $task = _get_task($args);
+  my $task = _get_task($args, $cmd);
 
   $task->check_running
     and die "Task ", $task->id, " is already running\n";
@@ -58,6 +62,7 @@ sub do_start {
     (
      cfg => $cfg,
      msg => \$msg,
+     foreground => $foreground,
     );
   $pid
     or die "$msg\n";
@@ -66,7 +71,7 @@ sub do_start {
 sub do_status {
   my ($args, $cfg) = @_;
 
-  my $task = _get_task($args);
+  my $task = _get_task($args, "status");
 
   print "Task Id: ", $task->id, "\n";
   print "Description: ", $task->description, "\n";
@@ -82,7 +87,7 @@ sub do_status {
 sub do_running {
   my ($args, $cfg) = @_;
 
-  my $task = _get_task($args);
+  my $task = _get_task($args, "running");
 
   exit $task->check_running ? 0 : 1;
 }
@@ -90,13 +95,81 @@ sub do_running {
 sub do_list {
   my ($args, $cfg) = @_;
 
-  for my $task (BSE::TB::BackgroundTasks->all) {
-    print $task->id, "\t", 
-      $task->check_running ? "Yes" : "No", "\t",
-       $task->last_started || "", "\t", 
-         $task->last_completion || "", "\t",
-           $task->last_exit || "", "\t", 
-             $task->task_pid || "", "\n";
+  my $fields = "id,running,started,completed,exit,signal,pid";
+  my $raw;
+
+  GetOptions("f=s", \$fields,
+            "r" => \$raw);
+
+  my @rows;
+
+  my @tasks;
+  my @matches;
+  if (@$args) {
+    for my $arg (@$args) {
+      my $work = $arg;
+      $work =~ s/\./\\./g;
+      $work =~ s/\*/.*/g;
+      $work =~ s/\?/.?/g;
+      push @matches, qr/^$work$/;
+    }
+
+  TASK:
+    for my $task (BSE::TB::BackgroundTasks->all) {
+      for my $match (@matches) {
+       if ($task->id =~ $match) {
+         push @tasks, $task;
+         next TASK;
+       }
+      }
+    }
+  }
+  else {
+    @tasks = BSE::TB::BackgroundTasks->all;
+  }
+
+  for my $task (@tasks) {
+    my $wait = $task->last_exit || 0;
+    push @rows,
+      {
+       id => $task->id,
+       running => $task->check_running ? "Yes" : "No",
+       started => $task->last_started || "",
+       completed => $task->last_completion || "",
+       exit => ($wait >> 8),
+       signal => ($wait & 0x7f),
+       pid => $task->task_pid || "",
+      };
+  }
+
+  my @fields = split /,/, $fields;
+
+  if ($raw) {
+    for my $row (@rows) {
+      print join("\t", @{$row}{@fields}), "\n";
+    }
+  }
+  else {
+    # calculate column widths
+    my %widths = map { $_ => 1 } @fields;
+    for my $row ({ map { $_ => $_ } @fields }, @rows) {
+      for my $field (@fields) {
+       if (length $row->{$field} > $widths{$field}) {
+         $widths{$field} = length $row->{$field};
+       }
+      }
+    }
+
+    for my $field (@fields) {
+      printf "%-*s|", $widths{$field}, $field;
+    }
+    print "\n";
+    for my $row (@rows) {
+      for my $field (@fields) {
+       printf "%-*s|", $widths{$field}, $row->{$field};
+      }
+      print "\n";
+    }
   }
 }
 
@@ -107,6 +180,7 @@ sub usage {
   die <<EOS;
 Usage: $0 <cmd> ...
 $0 start <taskid> - start the given task
+$0 run <taskid> - run in foreground
 $0 status <taskid> - display status of the task
 $0 running <taskid> - test if running (for shell scripts)
 $0 ls
index 152956e..7a4814e 100644 (file)
@@ -10,8 +10,9 @@ chdir "$FindBin::Bin/../cgi-bin"
   or warn "Could not change to cgi-bin directory: $!\n";
 Getopt::Long::Configure('bundling');
 my $verbose;
-GetOptions("v", \$verbose);
-$verbose = defined $verbose;
+GetOptions("v:i", \$verbose);
+defined $verbose && !$verbose
+  and $verbose = 1;
 
 my $cfg = bse_cfg;
 
index 655f8a9..d6d7712 100644 (file)
@@ -1,6 +1,7 @@
 #!perl -w
 use strict;
-use lib '../cgi-bin/modules';
+use FindBin;
+use lib "$FindBin::Bin/../cgi-bin/modules";
 use BSE::Cfg;
 use BSE::StorageMgr::Images;
 use BSE::StorageMgr::Files;