]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/support-scripts/marc_stream_importer.pl
Mid-overhaul, perldoc added
[working/Evergreen.git] / Open-ILS / src / support-scripts / marc_stream_importer.pl
1 #!/usr/bin/perl
2 # Copyright (C) 2008 Equinox Software, Inc.
3 # Author: Bill Erickson <erickson@esilibrary.com>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 =head1 NAME
16
17 marc_stream_importer.pl - Import MARC records via bare socket connection.
18
19 =head1 SYNOPSIS
20
21 ./marc_stream_importer.pl /openils/conf/opensrf_core.xml \
22     <eg_username> <eg_password> <bib_source> --port <port> --min_servers 2 \
23     --max_servers 20 --log_file /openils/var/log/marc_net_importer.log &
24
25 Note: this script has to be run in the same directory as oils_header.pl
26
27 =head1 DESCRIPTION
28
29 This script is a Net::Server::PreFork instance for shoving records into Evergreen from a remote system.
30
31 =head2 Configuration
32
33 =head3 OCLC Connexion
34
35 To use this script with OCLC Connexion, configure the client as follows:
36
37 Under Tools -> Options -> Export (tab)
38    Create -> Choose Connection -> OK -> Leave translation at "None" 
39        -> Create -> Create -> choose TCP/IP (internet) 
40        -> Enter hostname and Port, leave 'Use Telnet Protocol' checked 
41        -> Create/OK your way out of the dialogs
42    Record Characteristics (button) -> Choose 'UTF-8 Unicode' for the Character Set
43    
44
45 OCLC and Connexion are trademark/service marks of OCLC Online Computer Library Center, Inc.
46
47 =head1 CAVEATS
48
49 WARNING: This script provides no inherent security layer.  Any client that has 
50 access to the server+port can inject MARC records into the system.  
51 Use the available options (like allow/deny) in the Net::Server config file 
52 or via the command line to restrict access as necessary.
53
54 =head1 EXAMPLES
55
56 ./marc_stream_importer.pl /openils/conf/opensrf_core.xml \
57     admin open-ils connexion --port 5555 --min_servers 2 \
58     --max_servers 20 --log_file /openils/var/log/marc_net_importer.log &
59
60 =head1 SEE ALSO
61
62 L<Net::Server::PreFork>, L<marc_stream_importer.conf>
63
64 =head1 AUTHORS
65
66     Bill Erickson <erickson@esilibrary.com>
67     Joe Atzberger <jatzberger@esilibrary.com>
68
69
70 =cut
71
72 use strict; use warnings;
73 use Net::Server::PreFork;
74 use base qw/Net::Server::PreFork/;
75 use MARC::Record;
76 use MARC::Batch;
77 use MARC::File::XML;
78 use MARC::File::USMARC;
79 use File::Basename qw/fileparse/;
80
81 use OpenSRF::Utils::Logger qw/$logger/;
82 use OpenILS::Utils::Cronscript;
83 require 'oils_header.pl';
84 use vars qw/$apputils/;
85
86 # DEFAULTS
87 my $bufsize       = 4096;
88 my $wait_time     = 5;
89 my $bib_source    = 'connexion';
90 my $osrf_config   = '/openils/conf/opensrf_core.xml';
91 my $oils_username = 'admin';
92
93 # DEFAULTS for Net::Server
94 my $filename   = fileparse($0, '.pl');
95 my $conf_file  = (-r "$filename.conf") ? "$filename.conf" : undef;
96 # $conf_file is the Net::Server config for THIS script (not EG), if it exists and is readable
97
98 # $script->session('open-ils.cat') or die "No session created";
99
100 my $oils_password = shift;
101 my $authtoken;
102
103 sub warning {
104     return <<WARNING;
105
106 WARNING:  This script provides no security layer.  Any client that has 
107 access to the server+port can inject MARC records into the system.  
108
109 WARNING
110 }
111
112 print warning();
113 # $0 = 'Evergreen MARC Stream Listener';
114
115 sub process_request {
116     my $self = shift;
117     my $socket = $self->{server}->{client};
118     my $data = '';
119     my $buf;
120
121     # Reading <STDIN> blocks until the client is closed.  Instead of waiting 
122     # for that, give each inbound record $wait_time seconds to fully arrive
123     # and pull the data directly from the socket
124     eval {
125         local $SIG{ALRM} = sub { die "alarm\n" }; 
126         do {
127             alarm $wait_time;
128             last unless $socket->sysread($buf, $bufsize);
129             $data .= $buf;
130         } while(1);
131         alarm 0;
132     };
133
134     my $handle;
135     open $handle, '<', \$data; 
136     my $batch = MARC::Batch->new('USMARC', $handle);
137     $batch->strict_off;
138
139     my $index = 0;
140     while(1) {
141
142         my $rec;
143         $index++;
144
145         eval { $rec = $batch->next; };
146
147         if ($@) {
148             $logger->error("Failed parsing MARC record $index");
149             next;
150         }
151
152         last unless $rec;
153
154         my $resp = $apputils->simplereq(
155             'open-ils.cat', 
156             'open-ils.cat.biblio.record.xml.import',
157             $authtoken, 
158             $rec->as_xml_record, 
159             $bib_source
160         );
161
162         # has the session timed out?
163         if(oils_event_equals($resp, 'NO_SESSION')) {
164             set_auth_token();
165             my $resp = $apputils->simplereq(
166                 'open-ils.cat', 
167                 'open-ils.cat.biblio.record.xml.import',
168                 $authtoken, 
169                 $rec->as_xml_record, 
170                 $bib_source
171             );
172             oils_event_die($resp);
173         } else {
174             oils_event_die($resp);
175         }
176     }
177 }
178
179
180 # the authtoken will timeout after the configured inactivity period.
181 # When that happens, get a new one.
182 sub set_auth_token {
183     $authtoken = oils_login($oils_username, $oils_password, 'staff') 
184         or die "Unable to login to Evergreen";
185 }
186
187 osrf_connect($osrf_config);
188 set_auth_token();
189 __PACKAGE__->run();
190