00001 #!/usr/bin/perl -w
00002
00003 =head1 NAME
00004
00005 dbsf_daemon.pl
00006
00007 =head1 USAGE
00008
00009 * 'dsn|database_connection:s' => DSN connection file or text string for Drupal DB
00010
00011 You can check status or stop existing daemons by giving 'status' or 'stop', respectively
00012 You can optionally set dir with -dir (defaults to /tmp).
00013 If you're root, you can set effective user with -user (defaults to existing user). If using it for dbsf, we recommend setting it to your apache user.
00014 Note that all options can abbreviated with the first unique set of letters
00015
00016 =head1 TIPS
00017
00018 a dsn file is simple text file which has one line like this:
00019 dbi:Pg:dbname=InsectaCentral;host=localhost;port=15432;user=postgres;password=123321
00020
00021 Currently, only one environmental variable per software is allowed.
00022
00023 =head1 AUTHORS
00024
00025 Alexie Papanicolaou 1 2
00026
00027 1 Max Planck Institute for Chemical Ecology, Germany
00028 2 Centre for Ecology and Conservation, University of Exeter, UK
00029 alexie@butterflybase.org
00030
00031 =head1 DISCLAIMER & LICENSE
00032
00033 This software is released under the GNU General Public License version 3 (GPLv3).
00034 It is provided "as is" without warranty of any kind.
00035 You can find the terms and conditions at http://www.opensource.org/licenses/gpl-3.0.html.
00036 Please note that incorporating the whole software or parts of its code in proprietary software
00037 is prohibited under the current license.
00038
00039 =head1 BUGS & LIMITATIONS
00040
00041 None known so far. Please report them.
00042
00043 =cut
00044
00045 use strict;
00046 use Getopt::Long;
00047 use Pod::Usage;
00048 use POSIX qw(setsid setuid);
00049 use Fcntl ':flock';
00050 use DBI;
00051 use File::Basename;
00052 use Bio::SearchIO;
00053 use Bio::SearchIO::Writer::TextResultWriter;
00054 use Bio::SearchIO::Writer::HitTableWriter;
00055 use Bio::SearchIO::Writer::HTMLResultWriter;
00056 use Bio::SearchIO::Writer::GbrowseGFF;
00057 #use Bio::SearchIO::Writer::BSMLResultWriter;
00058 use Bio::Graphics;
00059 $| = 1;
00060
00061 # globals
00062 my $dsn =
00063 'dbi:Pg:dbname=drupal;host=localhost;port=5436;user=www-data;password=123';
00064 #### my $condor_submit=`which condor_submit`;chomp($condor_submit);
00065 my $dir = '/tmp';
00066 my $exist_user = `whoami`;
00067 chomp($exist_user);
00068
00069 # so that we can revert if needed
00070 my ( $exist_uid, $exist_gid ) = &get_uid($exist_user);
00071 my $user = $exist_user;
00072 my ( $condor, $help, %software_data, $logfile, $nosleep );
00073 my $dbprefix = ' ';
00074 my $cpus = 2;
00075 my $db_link;
00076 #debug
00077 use Data::Dumper;
00078 $dbprefix = 'ic_';
00079 #$db_link='http:
00080 $dsn =
00081 'dbi:Pg:dbname=ic-drupal-devel;host=blade6;port=5436;user=www-db;password=123';
00082 $dir = '/var/www/devel/sites/devel.insectacentral.ex.ac.uk/files/dbsf';
00083 GetOptions(
00084 'dsn:s' => \$dsn,
00085 'help' => \$help,
00086 'dir:s' => \$dir,
00087 'user:s' => \$user,
00088 'dbprefix:s' => \$dbprefix,
00089 'cpus:i' => \$cpus, # if no condor
00090 'nosleep' => \$nosleep,
00091 'db_link:s' => \$db_link, # for HMTL blast reports
00092 );
00093 if ( !$user || !$dir || $help ) { pod2usage; }
00094 ## If capturing a signal, unlock
00095 use sigtrap 'handler', \&unlock, 'normal-signals';
00096 umask 0;
00097 my $lock = $dir . '/blast_daemon.lock';
00098 my $action = shift if $ARGV[0];
00099 if ($action) {
00100 if ( $action =~ /stop/ ) {
00101 &killme();
00102 exit;
00103 } elsif ( $action =~ /status/ ) {
00104 &statusme();
00105 exit;
00106 } elsif ( $action =~ /start/ ) {
00107 } else {
00108 warn "Action can only be one of stop or status\n";
00109 pod2usage;
00110 }
00111 }
00112 print "\n";
00113 &get_pars();
00114 my ( $new_uid, $new_gid ) = &change_uid($user);
00115 &daemonize();
00116
00117 # Here is what the daemon actually does
00118 while (1) {
00119 &check_blast();
00120 sleep(5);
00121 &process_blast();
00122 sleep(10);
00123 }
00124 # before exiting while, unlock everything
00125 &unlock();
00126 ###
00127 sub daemonize() {
00128 chdir($dir) or die "Can't chdir to $dir: $!";
00129 if ( -s $lock ) {
00130 open( LOCK, $lock );
00131 while ( my $line = <LOCK> ) {
00132 if ( $line =~ /(\d+)/ ) {
00133 my $failure = `ps -A |grep $1`;
00134 if ( $failure =~ /^(\d+)/ ) {
00135 die "Program already running as pid $1.\n";
00136 }
00137 }
00138 }
00139 close LOCK;
00140 }
00141
00142 #two children down
00143 defined( my $pid = fork ) or die "Can't fork: $!";
00144 exit if $pid;
00145 defined( $pid = fork ) or die "Can't fork: $!";
00146 exit if $pid;
00147 setsid or die "Can't start a new session: $!";
00148 open( LOCK, ">$lock" ) or die "Cannot lock - $!\n";
00149 print LOCK $$
00150 . "\n"; ## pid of child (now master) -> write it in a lock file.
00151 my $locked = flock( LOCK, LOCK_EX ) or die "Cannot lock - $!\n";
00152 print "Started as pid $$\n";
00153 $logfile = "$dir/$$.log";
00154 open( LOG, ">$logfile" ) || die("Cannot write in $dir");
00155 opendir( BLASTDIR, $dir ) || die("Cannot open $dir\n");
00156 unlink("$dir/.test");
00157 open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
00158 open STDOUT, ">>$logfile" or die "Can't write to /dev/null: $!";
00159 open STDERR, ">>$logfile" or die "Can't write to /dev/null: $!";
00160 }
00161
00162 sub unlock() {
00163 flock( LOCK, LOCK_UN ) or die "Cannot unlock - $!\n";
00164 close(LOCK);
00165 unlink($lock);
00166 closedir(BLASTDIR);
00167 close LOG;
00168 exit;
00169 }
00170
00171 sub readlock() {
00172 print "Looking for LOCK at $lock\n";
00173 my $existing_pid;
00174 if ( -s $lock ) {
00175 open( LOCK, $lock );
00176 while ( my $line = <LOCK> ) {
00177 if ( $line =~ /(\d+)/ ) {
00178 my $pid_report = `ps -A |grep $1`;
00179 if ( $pid_report =~ /^\s*(\d+)/ ) {
00180 $existing_pid = $1;
00181 }
00182 }
00183 }
00184 close LOCK;
00185 }
00186 return $existing_pid;
00187 }
00188
00189 sub statusme() {
00190 my $existing_pid = &readlock();
00191 if ($existing_pid) {
00192 print "Running as $existing_pid\n";
00193 } else {
00194 print "Found no existing program\n";
00195 }
00196 }
00197
00198 sub killme() {
00199 my $existing_pid = &readlock();
00200 if ($existing_pid) {
00201 system("kill $existing_pid");
00202 print "Attempted to terminate existing program\n";
00203 return 1;
00204 } else {
00205 print "Found no existing program\n";
00206 return 0;
00207 }
00208 }
00209
00210 sub process_blast(){
00211 rewinddir(BLASTDIR);
00212 OUTER: while ( my $infile = readdir(BLASTDIR) ) {
00213 if ( $infile =~ /^(\w+)\.output$/ && -s $infile ) {
00214 my $uid = $1;
00215 if ($condor){
00216 my $check=`grep 'Normal termination' $uid.condor.log`;
00217 chomp($check);
00218 if (!$check) { next OUTER; }
00219 }
00220 else{
00221 my $check = `lsof|grep $infile`;
00222 chomp($check);
00223 if ($check) { next OUTER; }
00224 }
00225
00226 unless ( -s $uid . '.output.graph.png' ) {
00227 # make a graph
00228 # make csv
00229 # make a html
00230 # make tab -> bioperl broken.
00231 # make a gff3
00232 my $query_counter = 0;
00233
00234 #my $writer_tab = Bio::SearchIO::Writer::HitTableWriter->new();
00235 my $writer_html;
00236 if ($db_link){
00237 $writer_html = Bio::SearchIO::Writer::HTMLResultWriter->new(
00238 -nucleotide_url => $db_link,
00239 -protein_url => $db_link
00240 );
00241 }else{
00242 $writer_html = Bio::SearchIO::Writer::HTMLResultWriter->new();
00243 }
00244 $writer_html->title(\&blast_title);
00245 $writer_html->introduction(\&blast_intro);
00246 $writer_html->start_report(\&blast_head);
00247
00248 my $writer_gff = Bio::SearchIO::Writer::GbrowseGFF->new();
00249 my $writer_txt = Bio::SearchIO::Writer::TextResultWriter->new();
00250 my $in =
00251 new Bio::SearchIO( -format => 'blastxml', -file => $infile );
00252 my $max;
00253 while ( my $result = $in->next_result ) {
00254 $max = $result->query_length()
00255 if ( !$max || $max < $result->query_length() );
00256 }
00257
00258 #rewind
00259 $in =
00260 new Bio::SearchIO( -format => 'blastxml', -file => $infile );
00261 my $graph =
00262 Bio::Graphics::Panel->new(
00263 -length => $max,
00264 -width => 800,
00265 -pad_left => 10,
00266 -pad_right => 10,
00267 );
00268 while ( my $result = $in->next_result ) {
00269 my $query = $result->query_name();
00270 my $hitcount = $result->num_hits;
00271 #my @hit_array;
00272
00273 $query_counter++;
00274 if ( $hitcount && $hitcount > 0 ) {
00275
00276 #we want to know how many hits there are, only if there is a result do we bother...
00277 #my $out_tab =
00278 # new Bio::SearchIO( -writer => $writer_tab,
00279 # -file => ">>$infile.Query$query_counter.tab" );
00280 #my $out_tab_whole =
00281 # new Bio::SearchIO( -writer => $writer_tab,
00282 # -file => ">>$infile.tab" );
00283
00284 my $out_html =
00285 new Bio::SearchIO(
00286 -writer => $writer_html,
00287 -file => ">$infile.Query$query_counter.html"
00288 );
00289
00290 my $out_html_whole =
00291 new Bio::SearchIO( -writer => $writer_html,
00292 -file => ">>$infile.html"
00293 );
00294 my $out_txt =
00295 new Bio::SearchIO(
00296 -writer => $writer_txt,
00297 -file => ">$infile.Query$query_counter.txt"
00298 );
00299 my $out_txt_whole =
00300 new Bio::SearchIO( -writer => $writer_txt,
00301 -file => ">>$infile.txt" );
00302
00303 #graph starts in the result section and is built through the hits...
00304 my $full_length =
00305 Bio::SeqFeature::Generic->new(
00306 -start => 1,
00307 -end => $result->query_length,
00308 -display_name => $result->query_name,
00309 );
00310 $graph->add_track(
00311 $full_length,
00312 -glyph => 'arrow',
00313 -tick => 2,
00314 -fgcolor => 'black',
00315 -double => 1,
00316 -label => 1,
00317 );
00318 my $track = $graph->add_track(
00319 -glyph => 'graded_segments',
00320 -label => 1,
00321 -connector => 'dashed',
00322 -bgcolor => 'blue',
00323 -font2color => 'red',
00324 -sort_order => 'low_score',
00325 -description => sub {
00326 my $feature = shift;
00327 return unless $feature->has_tag('description');
00328 my ($description) =
00329 $feature->each_tag_value('description');
00330 my $score = $feature->score;
00331 "E=$score; $description";
00332 },
00333 );
00334 my $i = int(0);
00335 while ( my $hit = $result->next_hit ) {
00336 my $hitname=$hit->name;
00337 $hitname=~s/lcl\|
00338 my $description=$hit->description;
00339 $description=~s/No definition line found
00340 if ( $hit && $i < 20 ) {
00341 $i++;
00342 my $feature =
00343 Bio::SeqFeature::Generic->new(
00344 -score => $hit->significance,
00345 -display_name => $hitname,
00346 -tag =>
00347 { description => $description },
00348 );
00349 while ( my $hsp = $hit->next_hsp ) {
00350 $feature->add_sub_SeqFeature( $hsp,
00351 'EXPAND' );
00352 }
00353 $track->add_feature($feature);
00354 }
00355 }
00356
00357 # $out_tab->write_result($result);
00358 # $out_tab_whole->write_result($result);
00359 my $html_success =$out_html->write_result($result);
00360 $out_html_whole->write_result($result);
00361 $out_txt_whole->write_result($result);
00362 $out_txt->write_result($result);
00363 }
00364 }
00365 if ($graph) {
00366 open( GRAPH, ">$infile.graph.png" );
00367 print GRAPH $graph->png;
00368 close GRAPH;
00369 }
00370 }
00371 }
00372 }
00373 }
00374
00375
00376 sub check_blast() {
00377 rewinddir(BLASTDIR);
00378 OUTER: while ( my $file = readdir(BLASTDIR) ) {
00379 if ( $file =~ /^(\w+)\.wait$/ && -s $file) {
00380 my $uid = $1;
00381 unless ( -s $uid . '.done'
00382 || -s $uid . '.error'
00383 || -s $uid . '.output'
00384 || -s $uid . '.condor.submitted' )
00385 {
00386 my $software;
00387 my $par;
00388 my $env;
00389 open( FILE, $file ) || print "Cant open $file $!";
00390 while ( my $line = <FILE> ) {
00391 chomp($line);
00392 my @data = split( ':', $line );
00393 unless ( $data[1] ) { next; }
00394
00395 # security check
00396 if ( $data[0] eq 'uid' && $data[1] ne $uid ) {
00397 open( ER, ">$uid.error" );
00398 print ER "Failed $uid ne $data[1]\n";
00399 close ER;
00400 next OUTER;
00401 } elsif ( $data[0] eq 'par' ) {
00402 $par = $data[1];
00403 } elsif ( $data[0] eq 'software' ) {
00404 unless ( exists $software_data{ $data[1] } ) { next; }
00405 $software = $software_data{ $data[1] }{'exec'};
00406 }
00407 }
00408 close(FILE);
00409 unless ( $software && $par ) { next; }
00410 my $log = "Starting $software with $par";
00411 if ($condor) {
00412 my $me = `id`;
00413 if ( !-s "$uid.condor.submitted" ) {
00414 $log .= " using condor\n";
00415 print LOG $log;
00416 &prepare_condor( $uid, $software, $par );
00417 if ( -s "$uid.condor" ) {
00418 system(
00419 "$condor $uid.condor 1>> $logfile 2>>$logfile");
00420 system("date >$uid.condor.submitted");
00421 } else {
00422 open( ERROR, ">$uid.error" );
00423 print ERROR
00424 "Failed to find condor parameter file\n";
00425 close ERROR;
00426 }
00427 }
00428 } else {
00429 $log .= " without condor\n";
00430 print LOG $log;
00431 open( ERROR, ">$uid.error" );
00432 system("$software $par -a $cpus >>$logfile 2>>$logfile");
00433 if ( $? == -1 ) {
00434 print ERROR "failed to execute: $!\n";
00435 } elsif ( $? & 127 ) {
00436 printf ERROR "child died with signal %d, %s coredump\n",
00437 ( $? & 127 ), ( $? & 128 ) ? 'with' : 'without';
00438 } elsif ( $? != 0 ) {
00439 printf ERROR "child exited with value %d\n", $? >> 8;
00440 }
00441 close(ERROR);
00442
00443 # I/O friendship
00444 while ( ( !-s "$uid.output" || !-s $uid . '.error' )
00445 && !$nosleep )
00446 {
00447 sleep(5);
00448 }
00449 unless ( -s $uid . '.error' ) {
00450 rename( $uid . '.wait', $uid . '.done' );
00451 open( DONE, ">>$uid.done" );
00452 my $date = `date`;
00453 print DONE $date;
00454 close(DONE);
00455 unlink("$uid.error");
00456 }
00457 }
00458 }
00459 }
00460 }
00461 }
00462
00463 sub change_uid() {
00464 my $user = shift;
00465 my $me = `whoami`;
00466 chomp($me);
00467 my $uid = `id -u $user 2>/dev/null`;
00468 chomp($uid);
00469 my $gid = `id -g $user 2>/dev/null`;
00470 chomp($gid);
00471 if ( !$uid || !$gid ) {
00472 die "Cannot find user $user\n";
00473 }
00474 if ( $me ne $user ) {
00475 ## repeat group in effective gid to empty groups - Otherwise condor does not work
00476 $) = "$gid $gid";
00477 $( = $gid;
00478 setuid($uid);
00479 if ( $> ne $uid ) { die "Failed to change user to $uid, exiting.\n" }
00480 }
00481 print "Will run as $user ($uid,$gid)\n";
00482 return ( $uid, $gid );
00483 }
00484
00485 sub get_uid($) {
00486 my $user = shift;
00487 my $uid = `id -u $user`;
00488 chomp($uid);
00489 my $gid = `id -g $user`;
00490 chomp($gid);
00491 return ( $uid, $gid );
00492 }
00493
00494 sub connecttodb ($) {
00495 my $dsn = shift;
00496 my $dbConnectionSettings;
00497 if ( -s $dsn ) {
00498
00499 # Reading the database connection settings from a seperate file.
00500 # E.g. dbi:Pg:dbname=InsectaCentral;host=localhost;port=15432;user=postgres;password=123321
00501 open( DSN, $dsn ) || die("Error: Cannot open dsn file");
00502 my $dbConnectionSettings;
00503 while ( my $line = <DSN> ) {
00504 if ( $line =~ /^\s*#/ ) { next; }
00505 elsif ( $line =~ /^\s*(\S+)\s*$/ ) { $dbConnectionSettings = $1; }
00506 }
00507 close(DSN);
00508 } else {
00509 $dbConnectionSettings = $dsn;
00510 }
00511 my $dbh = DBI->connect($dbConnectionSettings);
00512 die("Error: Unable to connect to database") if ( !$dbh );
00513 return ($dbh);
00514 }
00515
00516 sub disconnectdb ($) {
00517 my $dbh = shift;
00518
00519 #Clean up
00520 $dbh->disconnect();
00521 }
00522
00523 sub get_pars() {
00524 if ( $dsn && -f $dsn ) {
00525 open( IN, $dsn );
00526 $dsn = "";
00527 while ( my $line = <IN> ) {
00528 unless ( $line =~ /^\s*$/ ) { chomp($line); $dsn .= $line; }
00529 }
00530 close(IN);
00531 }
00532 if ( !$dsn ) {
00533 die "No connection to database provided.\n";
00534 }
00535 my $dbh = &connecttodb($dsn)
00536 || die("Cannot connect to Drupal database...\n");
00537
00538 #get condor
00539 my $select_condor_sql =
00540 "SELECT active from "
00541 . $dbprefix
00542 . "ic_software where uniquename='condor'";
00543 my $select_condor_prepare = $dbh->prepare($select_condor_sql);
00544 $select_condor_prepare->execute();
00545 my $condor_hash = $select_condor_prepare->fetchrow_hashref;
00546 if ( $condor_hash->{'active'} == 1 ) {
00547 print
00548 "Utilizing Condor Distributed Computing service: Allowing all-write permissions for $dir\n";
00549 chmod( 0777, $dir );
00550 $condor = `which condor_submit`;
00551 chomp($condor);
00552 if ( !$condor ) {
00553 die
00554 "I'm sorry, but your condor has been set to active but cannot find the environmental variables for Condor. Are you sure the Apache user has sourced the condor env. variables? Also please don't run this using sudo but if needed, login as root.\n";
00555 }
00556 }
00557 $select_condor_prepare->finish();
00558
00559 # get executables
00560 my $select_software_sql =
00561 "SELECT uniquename from "
00562 . $dbprefix
00563 . "ic_software where active is true";
00564 my $select_software_prepare = $dbh->prepare($select_software_sql);
00565 $select_software_prepare->execute();
00566 while ( my $results_hash = $select_software_prepare->fetchrow_hashref ) {
00567 $software_data{ $results_hash->{'uniquename'} }{'exists'} = 1;
00568 }
00569 $select_software_prepare->finish();
00570 my $select_software_path_sql =
00571 "SELECT value FROM "
00572 . $dbprefix
00573 . "ic_softwareprop where software_id="
00574 . "(SELECT software_id from "
00575 . $dbprefix
00576 . "ic_software where uniquename=?)"
00577 . ' AND rank=0 AND type_id='
00578 . "(SELECT cvterm_id from "
00579 . $dbprefix
00580 . "ic_cvterm as cvterm JOIN "
00581 . $dbprefix
00582 . "ic_cv as cv on cv.cv_id=cvterm.cv_id"
00583 . " where cv.name='software path' AND cvterm.name=?)";
00584 my $select_software_path_prepare = $dbh->prepare($select_software_path_sql);
00585 foreach my $software ( keys %software_data ) {
00586 $select_software_path_prepare->execute( $software, 'executable' );
00587 my $results_hash1 = $select_software_path_prepare->fetchrow_hashref;
00588 $software_data{$software}{'exec'} = $results_hash1->{'value'}
00589 if $results_hash1->{'value'};
00590 $select_software_path_prepare->execute( $software, 'data' );
00591 my $results_hash2 = $select_software_path_prepare->fetchrow_hashref;
00592 $software_data{$software}{'env'} = $results_hash2->{'value'}
00593 if $results_hash2->{'value'};
00594 if ( $software eq 'blastall' ) {
00595 $ENV{'BLASTMAT'} = $software_data{$software}{'env'}
00596 if $software_data{$software}{'env'};
00597 }
00598 }
00599 $select_software_path_prepare->finish();
00600 &disconnectdb($dbh);
00601
00602 #just in case
00603 system("touch $dir/index.html");
00604 }
00605
00606 sub blast_title($){
00607 my $data=shift;
00608 my $alg=$data->{'_algorithm_version'};
00609 return "<b>$alg</b><h3>BLAST results</h3>";
00610 }
00611
00612 sub blast_head($) {
00613 return '
00614 <HTML>
00615 <HEAD>
00616 <TITLE>BLAST results</TITLE>
00617 </HEAD>
00618 <!------------------------------------------------------------------->
00619 <!-- Generated by Bio::SearchIO::Writer::HTMLResultWriter -->
00620 <!-- http://bioperl.org -->
00621 <!------------------------------------------------------------------->
00622 <BODY BGCOLOR="WHITE">
00623 ';
00624 }
00625
00626
00627 sub blast_intro($){
00628 my $data = shift;
00629 my $db=basename($data->database_name);
00630 $db=~s/\w+\.subject/user_uploaded_database/g;
00631 return '<p>'.sprintf(
00632 qq{
00633 <b>Query=</b> %s %s<br><dd>(%s letters)</dd>
00634 <p>
00635 <b>Database:</b> %s<br><dd>%s sequences; %s total letters<p></dd>
00636 <p>
00637 },$data->query_name,
00638 $data->query_description,
00639 &_numwithcommas($data->query_length),
00640 $db,
00641 &_numwithcommas($data->database_entries),
00642 &_numwithcommas($data->database_letters),
00643 ).'</p>';
00644 }
00645
00646 sub _numwithcommas {
00647 # from Perl Cookbook 2.17
00648 my $num = reverse( $_[0] );
00649 $num =~ s/(\d{3})(?=\d)(?!\d*\.)/$1,/g;
00650 return scalar reverse $num;
00651 }
00652
00653
00654 sub prepare_condor($$$) {
00655 my $uid = shift || warn("Cannot find UID\n");
00656 my $exec = shift || warn("Cannot find executable\n");
00657 my $data = shift || warn("No data");
00658 if ( !$uid || !$exec || !$data ) { return; }
00659 my @dbs = glob("$uid.subject*");
00660 my $tr_str = join( ",", @dbs ) if @dbs;
00661 $tr_str .= ",$uid.query";
00662 open( CONDOR, ">$uid.condor" ) || warn "Cannot not create $uid.condor $!\n";
00663 print CONDOR "Universe = vanilla\n";
00664 print CONDOR "Executable = $exec\n";
00665 print CONDOR "Initial_dir = $dir\n";
00666 print CONDOR "Notification = NEVER\n";
00667 print CONDOR "should_transfer_files = NO\n";
00668
00669 # print CONDOR "should_transfer_files = YES\n";
00670 # print CONDOR "transfer_input_files = $tr_str\n";
00671 # print CONDOR "transfer_output_files = $uid.output\n";
00672 # print CONDOR "when_to_transfer_output = ON_EXIT\n";
00673 print CONDOR "transfer_executable = FALSE\n";
00674 print CONDOR "log = $uid.condor.log\n";
00675
00676 #condor is absurd with error file permissions. print CONDOR "error = $uid.condor.err\n";
00677 print CONDOR "getenv = True\n";
00678 print CONDOR "Arguments = \"$data\"\n";
00679 print CONDOR " Queue\n";
00680 close CONDOR;
00681 ## dealing with condor's peculiarities...
00682 #system ("touch $dir/$uid.condor.err");
00683 #chmod (0666,"$dir/$uid.condor.err");
00684 return 1;
00685 }