-
Notifications
You must be signed in to change notification settings - Fork 54
/
zebraqueue_start.pl
executable file
·175 lines (164 loc) · 7.11 KB
/
zebraqueue_start.pl
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/usr/bin/perl
# script that starts the zebraquee
# Written by TG on 01/08/2006
use strict;
BEGIN {
# find Koha's Perl modules
# test carefully before changing this
use FindBin;
eval { require "$FindBin::Bin/../kohalib.pl" };
}
use C4::Context;
use C4::Biblio;
use C4::Search;
use C4::AuthoritiesMarc;
use XML::Simple;
use utf8;
### ZEBRA SERVER UPDATER
##Uses its own database handle
my $dbh=C4::Context->dbh;
my $readsth=$dbh->prepare("SELECT id,biblio_auth_number,operation,server FROM zebraqueue WHERE done=0
ORDER BY id DESC"); # NOTE - going in reverse order to catch deletes that
# occur after a string of updates (e.g., user deletes
# the items attached to a bib, then the items.
# Having a specialUpdate occur after a recordDelete
# should not occur.
#my $delsth=$dbh->prepare("delete from zebraqueue where id =?");
#AGAIN:
#my $wait=C4::Context->preference('zebrawait') || 120;
my $verbose = 0;
print "starting with verbose=$verbose\n" if $verbose;
my ($id,$biblionumber,$operation,$server,$marcxml);
$readsth->execute;
while (($id,$biblionumber,$operation,$server)=$readsth->fetchrow){
print "read in queue : $id : biblio $biblionumber for $operation on $server\n" if $verbose;
my $ok;
eval{
# if the operation is a deletion, zebra requires that we give it the xml.
# as it is no more in the SQL db, retrieve it from zebra itself.
# may sound silly, but that's the way zebra works ;-)
if ($operation =~ /delete/i) { # NOTE depending on version, delete operation
# was coded 'delete_record' or 'recordDelete'.
# 'recordDelete' is the preferred one, as that's
# what the ZOOM API wants.
# 1st read the record in zebra
my $Zconn=C4::Context->Zconn($server, 0, 1,'','xml');
my $query = $Zconn->search_pqf( '@attr 1=Local-Number '.$biblionumber);
# then, delete the record
$ok=zebrado($query->record(0)->render(),$operation,$server,$biblionumber);
# if it's an add or a modif
} else {
# get the XML
if ($server eq "biblioserver") {
my $marc = GetMarcBiblio($biblionumber);
$marcxml = $marc->as_xml_record() if $marc;
} elsif ($server eq "authorityserver") {
$marcxml =C4::AuthoritiesMarc::GetAuthorityXML($biblionumber);
}
if ($verbose) {
if ($marcxml) {
print "XML read : $marcxml\n" if $verbose >1;
} else {
# workaround for zebra bug needing a XML even for deletion
$marcxml= "<dummy/>";
print "unable to read MARCxml\n" if $verbose;
}
}
# check it's XML, just in case
eval {
my $hashed=XMLin($marcxml);
}; ### is it a proper xml? broken xml may crash ZEBRA- slow but safe
## it's Broken XML-- Should not reach here-- but if it does -lets protect ZEBRA
if ($@){
warn $@;
my $delsth=$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE id =?");
$delsth->execute($id);
next;
}
# ok, we have everything, do the operation in zebra !
$ok=zebrado($marcxml,$operation,$server);
}
};
print "ZEBRAopserver returned : $ok \n" if $verbose;
if ($ok ==1) {
$dbh=C4::Context->dbh;
my $delsth;
# if it's a deletion, we can delete every request on this biblio : in case the user
# did a modif (or item deletion) just before biblio deletion, there are some specialUpdage
# that are pending and can't succeed, as we don't have the XML anymore
# so, delete everything for this biblionumber
my $reset_readsth = 0;
if ($operation eq 'recordDelete') {
print "deleting biblio deletion $biblionumber\n" if $verbose;
$delsth =$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE biblio_auth_number =?");
$delsth->execute($biblionumber);
$reset_readsth = 1 if $delsth->rows() > 0;
# if it's not a deletion, delete every pending specialUpdate for this biblionumber
# in case the user add biblio, then X items, before this script runs
# this avoid indexing X+1 times where just 1 is enough.
} else {
print "deleting special date for $biblionumber\n" if $verbose;
$delsth =$dbh->prepare("UPDATE zebraqueue SET done=1 WHERE biblio_auth_number =? and operation='specialUpdate'");
$delsth->execute($biblionumber);
$reset_readsth = 1 if $delsth->rows() > 0;
}
if ($reset_readsth) {
# if we can ignore rows in zebraqueue because we've already
# touched a record, reset the query.
$readsth->finish();
$readsth->execute();
}
}
}
sub zebrado {
###Accepts a $server variable thus we can use it to update biblios, authorities or other zebra dbs
my ($record,$op,$server,$biblionumber)=@_;
my @port;
my $tried=0;
my $recon=0;
my $reconnect=0;
# $record=Encode::encode("UTF-8",$record);
my $shadow=$server."shadow";
$op = 'recordDelete' if $op eq 'delete_record';
reconnect:
my $Zconn=C4::Context->Zconn($server, 0, 1);
if ($record){
print "updating $op on $biblionumber for server $server\n $record\n" if $verbose;
my $Zpackage = $Zconn->package();
$Zpackage->option(action => $op);
$Zpackage->option(record => $record);
# $Zpackage->option(recordIdOpaque => $biblionumber) if $biblionumber;
retry:
$Zpackage->send("update");
my($error, $errmsg, $addinfo, $diagset) = $Zconn->error_x();
if ($error==10007 && $tried<3) {## timeout --another 30 looonng seconds for this update
print "error 10007\n" if $verbose;
sleep 1; ## wait a sec!
$tried=$tried+1;
goto "retry";
}elsif ($error==2 && $tried<2) {## timeout --temporary zebra error !whatever that means
print "error 2\n" if $verbose;
sleep 2; ## wait two seconds!
$tried=$tried+1;
goto "retry";
}elsif($error==10004 && $recon==0){##Lost connection -reconnect
print "error 10004\n" if $verbose;
sleep 1; ## wait a sec!
$recon=1;
$Zpackage->destroy();
$Zconn->destroy();
goto "reconnect";
}elsif ($error){
# warn "Error-$server $op /errcode:, $error, /MSG:,$errmsg,$addinfo \n";
print "error $error\n" if $verbose;
$Zpackage->destroy();
$Zconn->destroy();
return 0;
}
$Zpackage->send('commit');
# $Zpackage->destroy();
# $Zconn->destroy();
return 1;
}
return 0;
}