3 ## radsqlrelay.pl This program tails a SQL logfile and forwards
4 ## the queries to a database server. Used to
5 ## replicate accounting records to one (central)
6 ## database, even if the database has extended
11 ## Author: Nicolas Baradakis <nicolas.baradakis@cegetel.net>
13 ## Copyright (C) 2005 Cegetel
15 ## This program is free software; you can redistribute it and/or
16 ## modify it under the terms of the GNU General Public License
17 ## as published by the Free Software Foundation; either version 2
18 ## of the License, or (at your option) any later version.
20 ## This program is distributed in the hope that it will be useful,
21 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ## GNU General Public License for more details.
25 ## You should have received a copy of the GNU General Public License
26 ## along with this program; if not, write to the Free Software
27 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
33 use POSIX qw(:unistd_h :errno_h);
45 # /!\ OS-dependent structure
52 # c2ph says: typedef='s2 l2 i', sizeof=16
53 my $FLOCK_STRUCT = 's2l2i';
57 my ($fh, $start, $len) = @_;
58 $start = 0 unless defined $start;
59 $len = 0 unless defined $len;
61 #type whence start till pid
62 my $packed = pack($FLOCK_STRUCT, F_WRLCK, SEEK_SET, $start, $len, 0);
63 if (fcntl($fh, F_SETLKW, $packed)) { return 1 }
70 usage: radsqlrelay [options] file_path
72 -? Print this help message.
73 -1 One-shot mode: push the file to database and exit.
74 -b database Name of the database to use.
75 -d sql_driver Driver to use: mysql, pg, oracle.
76 -f file Read password from file, instead of command line.
77 -h host Connect to host.
78 -P port Port number to use for connection.
79 -p passord Password to use when connecting to server.
80 -u user User for login.
90 $dbh = DBI->connect($dbinfo->{base}, $dbinfo->{user}, $dbinfo->{pass},
91 { RaiseError => 0, PrintError => 0,
96 $dbinfo->{handle} = $dbh;
101 my ($dbinfo, $path) = @_;
103 unless (-e $path.'.work') {
104 until (rename($path, $path.'.work')) {
107 return if $need_exit;
109 print STDERR "error: Couldn't move $path to $path.work: $!\n";
115 open(FILE, "+< $path.work") or die "error: Couldn't open $path.work: $!\n";
116 setlock(\*FILE) or die "error: Couldn't lock $path.work: $!\n";
119 chomp(my $query = $_);
120 until ($dbinfo->{handle}->do($query)) {
121 print $dbinfo->{handle}->errstr."\n";
122 if ($dbinfo->{handle}->ping) {
125 print "error: Lost connection to database\n";
126 $dbinfo->{handle}->disconnect;
127 connect_wait($dbinfo);
132 unlink($path.'.work');
133 close(FILE); # and unlock
145 my $ret = getopts("b:d:f:h:P:p:u:x1?", \%args);
146 if (!$ret or @ARGV != 1) {
156 if (lc($args{d}) eq 'mysql') {
157 $data_source = "DBI:mysql:database=$args{b};host=$args{h}";
158 } elsif (lc($args{d}) eq 'pg') {
159 $data_source = "DBI:Pg:dbname=$args{b};host=$args{h}";
160 } elsif (lc($args{d}) eq 'oracle') {
161 $data_source = "DBI:Oracle:$args{b}";
163 print STDERR "error: SQL driver not supported yet: $args{d}\n";
166 $data_source .= ";port=$args{P}" if $args{'P'};
170 open(FILE, "< $args{f}") or die "error: Couldn't open $args{f}: $!\n";
175 # args{p} is always defined.
179 $SIG{INT} = \&got_signal;
180 $SIG{TERM} = \&got_signal;
183 base => $data_source,
187 connect_wait(\%dbinfo);
189 my $path = shift @ARGV;
192 process_file(\%dbinfo, $path);
193 last if ($args{1} || $need_exit);
197 $dbinfo{handle}->disconnect;