|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Test::postgresql;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
172997
 | 
 use strict;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
197
 | 
    | 
| 
4
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
26
 | 
 use warnings;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
142
 | 
    | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
140
 | 
 use 5.008;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
183
 | 
    | 
| 
7
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
5078
 | 
 use Class::Accessor::Lite;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5841
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
32
 | 
    | 
| 
8
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
235
 | 
 use Cwd;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
443
 | 
    | 
| 
9
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
2622
 | 
 use DBI;  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19585
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
235
 | 
    | 
| 
10
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
6546
 | 
 use File::Temp qw(tempdir);  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
141189
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
395
 | 
    | 
| 
11
 | 
5
 | 
 
 | 
 
 | 
  
5
  
 | 
 
 | 
4430
 | 
 use POSIX qw(SIGTERM WNOHANG setuid);  | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
42538
 | 
    | 
| 
 
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
40
 | 
    | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $VERSION = '0.09';  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our @SEARCH_PATHS = (  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # popular installtion dir?  | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     qw(/usr/local/pgsql),  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # ubuntu (maybe debian as well, find the newest version)  | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     (sort { $b cmp $a } grep { -d $_ } glob "/usr/lib/postgresql/*"),  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # macport  | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     (sort { $b cmp $a } grep { -d $_ } glob "/opt/local/lib/postgresql-*"),  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $errstr;  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our $BASE_PORT = 15432;  | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 our %Defaults = (  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     auto_start      => 2,  | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     base_dir        => undef,  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     initdb          => undef,  | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     initdb_args     => '-U postgres -A trust',  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     pid             => undef,  | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     port            => undef,  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     postmaster      => undef,  | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     postmaster_args => '-h 127.0.0.1',  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     uid             => undef,  | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     _owner_pid      => undef,  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Class::Accessor::Lite->mk_accessors(keys %Defaults);  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
43
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
1
  
 | 
837
 | 
     my $klass = shift;  | 
| 
44
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $self = bless {  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         %Defaults,  | 
| 
46
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
83
 | 
         @_ == 1 ? %{$_[0]} : @_,  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         _owner_pid => $$,  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }, $klass;  | 
| 
49
 | 
4
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
31
 | 
     if (! defined $self->uid && $ENV{USER} eq 'root') {  | 
| 
50
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my @a = getpwnam('nobody')  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "user nobody does not exist, use uid() to specify user:$!";  | 
| 
52
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->uid($a[2]);  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
54
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
816
 | 
     if (defined $self->base_dir) {  | 
| 
55
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->base_dir(cwd . '/' . $self->base_dir)  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if $self->base_dir !~ m|^/|;  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
58
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
66
 | 
         $self->base_dir(  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             tempdir(  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 CLEANUP => $ENV{TEST_POSTGRESQL_PRESERVE} ? undef : 1,  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ),  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
| 
63
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
3148
 | 
         chown $self->uid, -1, $self->base_dir  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if defined $self->uid;  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
66
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
58
 | 
     if (! defined $self->initdb) {  | 
| 
67
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
43
 | 
         my $prog = _find_program('initdb')  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or return;  | 
| 
69
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->initdb($prog);  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
71
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if (! defined $self->postmaster) {  | 
| 
72
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $prog = _find_program('postmaster')  | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or return;  | 
| 
74
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->postmaster($prog);  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
76
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($self->auto_start) {  | 
| 
77
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->setup  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if $self->auto_start >= 2;  | 
| 
79
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         $self->start;  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
81
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self;  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub DESTROY {  | 
| 
85
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
28
 | 
     my $self = shift;  | 
| 
86
 | 
4
 | 
  
 50
  
 | 
  
 33
  
 | 
 
 | 
 
 | 
253
 | 
     $self->stop  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if defined $self->pid && $$ == $self->_owner_pid;  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub dsn {  | 
| 
91
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self, %args) = @_;  | 
| 
92
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $args{host} ||= '127.0.0.1';  | 
| 
93
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $args{port} ||= $self->port;  | 
| 
94
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $args{user} ||= 'postgres';  | 
| 
95
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $args{dbname} ||= 'test';  | 
| 
96
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return 'DBI:Pg:' . join(';', map { "$_=$args{$_}" } sort keys %args);  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub start {  | 
| 
100
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my $self = shift;  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return  | 
| 
102
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if defined $self->pid;  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # start (or die)  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     sub {  | 
| 
105
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
         my $err;  | 
| 
106
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if ($self->port) {  | 
| 
107
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $err = $self->_try_start($self->port)  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or return;  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # try by incrementing port no  | 
| 
111
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             for (my $port = $BASE_PORT; $port < $BASE_PORT + 100; $port++) {  | 
| 
112
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 $err = $self->_try_start($port)  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     or return;  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # failed  | 
| 
117
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         die "failed to launch postgresql:$!\n$err";  | 
| 
118
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     }->();  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     { # create "test" database  | 
| 
120
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $dbh = DBI->connect($self->dsn(dbname => 'template1'), '', '', {})  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die $DBI::errstr;  | 
| 
122
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if ($dbh->selectrow_arrayref(q{SELECT COUNT(*) FROM pg_database WHERE datname='test'})->[0] == 0) {  | 
| 
123
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $dbh->do('CREATE DATABASE test')  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or die $dbh->errstr;  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _try_start {  | 
| 
130
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
 
 | 
0
 | 
     my ($self, $port) = @_;  | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # open log and fork  | 
| 
132
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     open my $logfh, '>', $self->base_dir . '/postgres.log'  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or die 'failed to create log file:' . $self->base_dir  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             . "/postgres.log:$!";  | 
| 
135
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     my $pid = fork;  | 
| 
136
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     die "fork(2) failed:$!"  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         unless defined $pid;  | 
| 
138
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($pid == 0) {  | 
| 
139
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         open STDOUT, '>&', $logfh  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "dup(2) failed:$!";  | 
| 
141
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         open STDERR, '>&', $logfh  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "dup(2) failed:$!";  | 
| 
143
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         chdir $self->base_dir  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "failed to chdir to:" . $self->base_dir . ":$!";  | 
| 
145
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if (defined $self->uid) {  | 
| 
146
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             setuid($self->uid)  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or die "setuid failed:$!";  | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
149
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $cmd = join(  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             ' ',  | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->postmaster,  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             $self->postmaster_args,  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             '-p', $port,  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             '-D', $self->base_dir . '/data',  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             '-k', $self->base_dir . '/tmp',  | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         );  | 
| 
157
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         exec($cmd);  | 
| 
158
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         die "failed to launch postmaster:$?";  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
160
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     close $logfh;  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # wait until server becomes ready (or dies)  | 
| 
162
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     for (my $i = 0; $i < 100; $i++) {  | 
| 
163
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         open $logfh, '<', $self->base_dir . '/postgres.log'  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die 'failed to open log file:' . $self->base_dir  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 . "/postgres.log:$!";  | 
| 
166
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $lines = do { join '', <$logfh> };  | 
| 
 
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
    | 
| 
167
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         close $logfh;  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         last  | 
| 
169
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             if $lines =~ /is ready to accept connections/;  | 
| 
170
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if (waitpid($pid, WNOHANG) > 0) {  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             # failed  | 
| 
172
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             return $lines;  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
174
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         sleep 1;  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # postgresql is ready  | 
| 
177
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->pid($pid);  | 
| 
178
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->port($port);  | 
| 
179
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     return;  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub stop {  | 
| 
183
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my ($self, $sig) = @_;  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     return  | 
| 
185
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         unless defined $self->pid;  | 
| 
186
 | 
0
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
0
 | 
     $sig ||= SIGTERM;  | 
| 
187
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     kill $sig, $self->pid;  | 
| 
188
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     while (waitpid($self->pid, 0) <= 0) {  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
190
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     $self->pid(undef);  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub setup {  | 
| 
194
 | 
0
 | 
 
 | 
 
 | 
  
0
  
 | 
  
1
  
 | 
0
 | 
     my $self = shift;  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # (re)create directory structure  | 
| 
196
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     mkdir $self->base_dir;  | 
| 
197
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     chmod 0755, $self->base_dir  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         or die "failed to chmod 0755 dir:" . $self->base_dir . ":$!";  | 
| 
199
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if ($ENV{USER} eq 'root') {  | 
| 
200
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         chown $self->uid, -1, $self->base_dir  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "failed to chown dir:" . $self->base_dir . ":$!";  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
203
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if (mkdir $self->base_dir . '/tmp') {  | 
| 
204
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if ($self->uid) {  | 
| 
205
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             chown $self->uid, -1, $self->base_dir . '/tmp'  | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or die "failed to chown dir:" . $self->base_dir . "/tmp:$!";  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # initdb  | 
| 
210
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
     if (! -d $self->base_dir . '/data') {  | 
| 
211
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         pipe my $rfh, my $wfh  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             or die "failed to create pipe:$!";  | 
| 
213
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $pid = fork;  | 
| 
214
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         die "fork failed:$!"  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             unless defined $pid;  | 
| 
216
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if ($pid == 0) {  | 
| 
217
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             close $rfh;  | 
| 
218
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             open STDOUT, '>&', $wfh  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or die "dup(2) failed:$!";  | 
| 
220
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             open STDERR, '>&', $wfh  | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or die "dup(2) failed:$!";  | 
| 
222
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             chdir $self->base_dir  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 or die "failed to chdir to:" . $self->base_dir . ":$!";  | 
| 
224
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             if (defined $self->uid) {  | 
| 
225
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 setuid($self->uid)  | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                     or die "setuid failed:$!";  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
228
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             my $cmd = join(  | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 ' ',  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $self->initdb,  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 $self->initdb_args,  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                 '-D', $self->base_dir . '/data',  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             );  | 
| 
234
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             exec($cmd);  | 
| 
235
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             die "failed to exec:$cmd:$!";  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
237
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         close $wfh;  | 
| 
238
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         my $output = '';  | 
| 
239
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         while (my $l = <$rfh>) {  | 
| 
240
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $output .= $l;  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
242
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         close $rfh;  | 
| 
243
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         while (waitpid($pid, 0) <= 0) {  | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
245
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         die "*** initdb failed ***\n$output\n"  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if $? != 0;  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _find_program {  | 
| 
251
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
11
 | 
     my $prog = shift;  | 
| 
252
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     undef $errstr;  | 
| 
253
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     my $path = _get_path_of($prog);  | 
| 
254
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
61
 | 
     return $path  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if $path;  | 
| 
256
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
91
 | 
     for my $sp (@SEARCH_PATHS) {  | 
| 
257
 | 
3
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
504
 | 
         return "$sp/bin/$prog"  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             if -x "$sp/bin/$prog";  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
260
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
110
 | 
     $errstr = "could not find $prog, please set appropriate PATH";  | 
| 
261
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
502
 | 
     return;  | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _get_path_of {  | 
| 
265
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
 
 | 
9
 | 
     my $prog = shift;  | 
| 
266
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
43465
 | 
     my $path = `which $prog 2> /dev/null`;  | 
| 
267
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
213
 | 
     chomp $path  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         if $path;  | 
| 
269
 | 
4
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
132
 | 
     $path = ''  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         unless -x $path;  | 
| 
271
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
171
 | 
     $path;  | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 1;  | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |