~tenbrae/mycat/trunk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package Mycat::scp;

use vars qw($VERSION $Timeout $Flush $PreserveDuringSCP $RecurseDuringSCP);
use strict;

$VERSION = '0.1';
$Timeout = 10;
$Flush = 1;
$PreserveDuringSCP = 1;
$RecurseDuringSCP  = 0;

use POSIX ":sys_wait_h";
use Mycat::TraceMessages qw(t tt ttt p pe);

delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};   # Make %ENV safer
$ENV{'PATH'} = '/bin:/usr/bin';

=pod

=head1 NAME

Mycat::scp - Perl extension for MySQL Cluster Administration Tools

=head1 DESCRIPTION

Mycat is a collection of utilities for use in monitoring database clusters.

=head1 SYNOPSIS

# specify options to SCP
$Mycat::scp::PreserveDuringSCP = 1; // preserve file modification times
$Mycat::scp::RecurseDuringSCP  = 0; // do not recursively copy directories

# instantiate Mycat::scp objects
my $s = Mycat::scp::new('/path/to/local/file','[user@]host:/path/to/[file]');
 
# execute copy and retrieve result when finished
$Mycat::scp::Flush = 0;
my $result = $s->execute(); 
print $result;

# alternately, print results as they come back from remote server
$Mycat::scp::Flush = 1;
$s->execute();

=head1 USAGE

=over

=cut

# Mycat::scp::new {{{
=pod

=item Mycat::scp::new($origin,$destination)

 Initialize a new scp object.
 Both parameters are required.
 This function merely instantiates the object for further use.

    my $s = Mycat::scp::new('/path/to/local/file','[user@]host:/path/to/[file]');

=cut
sub new ($$)
{
	my $class = shift;
	my $self = {};
	$self->{origin} = shift or die("Mycat::scp::new called without origin");
	$self->{destin} = shift or die("Mycat::scp::new called without destination");
	$self->{result} = undef;
	bless ($self, $class);
	return $self;
} #}}}

# Mycat::scp::execute {{{
=pod

=item $s->execute()

 This is the workhorse of Mycat's SCP functions, spawning a child process to 
 encapsulate the SCP connection, passing the result back through shared memory.

 Timeout can be controlled via the variable ::Timeout, default is 10sec

 To see the internal workings of this function, turn trace debugging to level 3.

=cut
sub execute()
{
	my $self = shift;
	$self->{result} = '';
	my $itime = time;

    my $options;
    if ( $PreserveDuringSCP or $RecurseDuringSCP ) { 
        $options = '-';
        $options .= 'p' if $PreserveDuringSCP;
        $options .= 'r' if $RecurseDuringSCP;
    }

    tt('SCP: Copying ['.$self->{origin}.'] to ['.$self->{destin}.']...');
	
    my $childpid;
    
	if ( defined($options) ) {
        $childpid = open KID, '-|', 'scp', $options, $self->{origin}, $self->{destin};
    } else {
        $childpid = open KID, '-|', 'scp', $self->{origin}, $self->{destin};
    }

	ttt('SCP: forked and waiting for subprocess to finish');

	my $kid;
	my $itime = time;

	eval {
		local $SIG{ALRM} = sub { pe('Sending kill (9) signal to SCP after waiting '.$Timeout.' seconds'); kill 9, $childpid; };
		alarm $Timeout unless $Timeout == 0;
		while(<KID>) {
			$self->{result} .= $_;
			if ( $Flush ) {
				chomp($_);
				p($_);
			}
		}
		alarm 0;
	};
	
	close KID || pe('SCP exited with abnormal status: '.$?);
	ttt('SCP: done');
	return $self->{result};
}

1;

=pod

=head1 AUTHOR

 Devananda van der Veen
 devananda.vdv@gmail.com

=cut

__END__