4 use vars qw( $source_directory $destination_host $destination_root
5 $lock_directory $archive_directory $failed_directory
7 $log_file $protocol $user $password
8 $mail_from @mail_to @mail_command
9 $date_format $time_format
11 use vars qw ( $retry $retrytime $overwrite ); #per-process globals, yuck
12 use subs qw( daemonize archive failed movefile docopy logsuccess logfail
13 email datestamp _logmsg
25 $SIG{__DIE__} = \&_die;
26 $SIG{__WARN__} = \&_logmsg;
28 $SIG{CHLD} = 'IGNORE'; #zombie prevention
31 $SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; };
33 #require "/etc/digitiz-xfer.conf";
34 require "/home/ivan/digitiz/digitiz-xfer.conf";
40 opendir(DIR, $source_directory)
41 || die "can't opendir $source_directory: $!";
42 while ( my $file = readdir DIR ) {
44 warn "parent process exiting (transfers in progress will finish)\n";
47 next if $file =~ /^\.\.?/;
51 # my $lock = new IO::File ">>$lock_directory/$file"
52 # or die "Couldn't open lockfile $lock_directory/$file: $!";
53 # next unless flock($lock, LOCK_EX|LOCK_NB);
54 # unless ( -e "$source_directory/$file" ) { #make sure file's still here
55 # unlink "$lock_directory/$file";
56 # flock($lock, LOCK_UN);
60 #fork a kid for the rest (can't be sure locks will get inherited -
63 defined( my $pid = fork ) or die "can't fork: $!";
66 local $SIG{HUP} = 'IGNORE';
67 local $SIG{INT} = 'IGNORE';
68 local $SIG{QUIT} = 'IGNORE';
69 local $SIG{TERM} = 'IGNORE';
70 local $SIG{TSTP} = 'IGNORE';
71 local $SIG{PIPE} = 'IGNORE';
73 #locking foo, here instead
74 my $lock = new IO::File "+>>$lock_directory/$file" #touch
75 or die "Couldn't open lockfile $lock_directory/$file: $!";
76 #next unless flock($lock, LOCK_EX|LOCK_NB);
77 exit unless flock($lock, LOCK_EX|LOCK_NB);
78 unless ( -e "$source_directory/$file" ) { #make sure file's still here
79 unlink "$lock_directory/$file";
80 flock($lock, LOCK_UN);
86 chomp( $retry = <$lock> || 0 );
87 chomp( $retrytime = <$lock> || 0 );
88 chomp( $overwrite = <$lock> || 0 );
90 if ( $retrytime && (time-$retrytime)/3600 >= 48 ) {
91 logfail($file, "still can't transfer $file after 48 hours");
94 #next if ($retry-1) > ((time-$retrytime)/3600);
95 exit if ($retry-1) > ((time-$retrytime)/3600);
97 if ( $file =~ /^([\d\-]+)\.\w+$/ ) {
99 if ( $sku = new Digitiz_It::SKU $1 ) {
102 logfail($file, "can't parse SKU: $1: $Digitiz_It::SKU::ERROR");
106 logfail($file, "can't parse filename for SKU");
112 #why doesn't this work? seek($lock, 0, 0);
113 my $newlock = new IO::File ">$lock_directory/$file.tmp";
114 print $newlock "$retry\n$retrytime\n$overwrite\n";
116 rename "$lock_directory/$file.tmp", "$lock_directory/$file";
118 unlink "$lock_directory/$file";
120 flock($lock, LOCK_UN);
124 sleep 2; #don't spawn too fast!
131 chdir "$source_directory" or die "Can't chdir to $source_directory: $!";
132 open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
133 # open STDOUT, '>/dev/null'
134 # or die "Can't write to /dev/null: $!";
135 defined(my $pid = fork) or die "Can't fork: $!";
137 print "digitiz-xfer started with pid $pid; logging to $log_file\n";
138 warn "digitiz-xfer parent started with pid $pid\n";
139 exit unless $pid_file;
140 my $pidfh = new IO::File ">$pid_file" or exit;
141 print $pidfh "$pid\n";
144 open STDOUT, '>/dev/null'
145 or die "Can't write to /dev/null: $!";
146 setsid or die "Can't start a new session: $!";
147 open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
150 sub archive { #archives a file
152 my $d = &datestamp();
153 _logmsg("archiving $source_directory/$file in $archive_directory/$d/$file");
154 movefile($file, "$archive_directory/$d" );
157 sub failed { #failed files
159 _logmsg("moving $source_directory/$file to $failed_directory/$file");
160 movefile($file, "$failed_directory");
164 my( $file, $dir ) = @_;
167 or die "fatal: can't mkdir $dir: $!";
168 rename "$source_directory/$file", "$dir/$file"
169 or die "fatal: cant't rename $source_directory/$file to $dir/$file: $!";
172 sub docopy { #copies a file to the remote host
173 my($file, $sku) = @_;
176 if ( $protocol eq 'scp' ) {
177 $xfer = Net::SCP->new($destination_host);
178 } elsif ( $protocol eq 'ftp' ) {
179 $xfer = Net::FTP->new($destination_host);
181 die "unknown transfer protocol $protocol";
186 logrepeatfail($file, "can't attempt transfer: $@");
188 logfail($file, "can't attempt transfer: $@");
194 $xfer->login($user, $password) or do {
196 logrepeatfail($file, "can't login");
198 logfail($file, "can't login");
204 $xfer->binary or do {
206 logrepeatfail($file, "can't set binary mode");
208 logfail($file, "can't set binary mode");
213 "$destination_root/". $sku->account. '/'. $sku->library. '/';
214 $dest_path .= 'Thumbnails/' if $sku->thumbnail;
216 my $dest_file = $dest_path. $file;
218 if ( $xfer->size($dest_file) && ! $overwrite ) {
219 logfail($file, "file $dest_file already exists on remote host");
224 _logmsg("copying $source_directory/$file to ".
225 "$destination_host:$dest_file with $protocol");
228 if ( $protocol eq 'ftp' ) { #so close
229 $xfer->cwd(dirname($dest_file));
230 $dest_file = basename($dest_file);
232 $xfer->put("$source_directory/$file", $dest_file);
234 my $localsize = -s "$source_directory/$file";
235 my $remotesize = $xfer->size($dest_file);
237 if ( $localsize && ( $localsize == $remotesize ) ) {
243 "verification failed: local $localsize, remote $remotesize"
247 "verification failed: local $localsize, remote $remotesize"
258 warn "transfer of $file successful\n";
259 email('Delivered','', $file);
263 my ($file, $err) = @_;
264 warn "[$file] $err\n";
265 email('Error', $err, $file);
269 my ($file, $err) = @_;
270 warn "[$file] $err\n";
274 my ( $status, $error, $file ) = @_;
275 my $mail = new Mail::Mailer @mail_command;
277 'From' => $mail_from,
278 'To' => [ @mail_to ],
279 'Subject' => "$file transfer status",
282 my $date = time2str($date_format, $now);
283 my $time = time2str($time_format, $now);
291 print $mail "Error: $error\n" if $error;
296 time2str("%m%d%Y", time);
301 email('Fatal', $msg, "Fatal");
306 chomp( my $msg = shift );
307 my $log = new IO::File ">>$log_file";
308 flock($log, LOCK_EX);
310 print $log "[". time2str("%a %b %e %T %Y",time). "] [$$] $msg\n";
311 flock($log, LOCK_UN);