]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/support-scripts/test-scripts/unapi_bench.pl
Merge branch 'master' of git.evergreen-ils.org:Evergreen into template-toolkit-opac
[working/Evergreen.git] / Open-ILS / src / support-scripts / test-scripts / unapi_bench.pl
1 #!/usr/bin/perl
2 require '../oils_header.pl';
3 use strict; use warnings;
4 use Time::HiRes qw/time usleep/;
5 use Data::Dumper;
6 use OpenSRF::Utils::JSON;
7 use OpenILS::Utils::CStoreEditor;
8 use XML::LibXML;
9
10 #-----------------------------------------------------------------------------
11 # Does a checkout, renew, and checkin 
12 #-----------------------------------------------------------------------------
13
14 my @recs = (1,2,3,4,5,6,7,8,9,10);
15
16 osrf_connect(shift() || '/openils/conf/opensrf_core.xml');
17
18 my $e = OpenILS::Utils::CStoreEditor->new;
19
20 sub xptext {
21     my($node, $path) = @_;
22     #my $res = $node->findnodes($path);
23     my $res = $node->find($path);
24     return '' unless $res and $res->[0];
25     return $res->[0]->textContent;
26 }
27
28 sub get_bib_attrs {
29     my $xml = shift;
30     return {
31         isbn => xptext($xml, '*[@tag="020"]/*[@code="a"]'),
32         upc => xptext($xml,'*[@tag="024"]/*[@code="a"]'),
33         issn => xptext($xml,'*[@tag="022"]/*[@code="a"]'),
34         title => xptext($xml,'*[@tag="245"]/*[@code="a"]'),
35         author => xptext($xml,'*[@tag="100"]/*[@code="a"]'),
36         publisher => xptext($xml,'*[@tag="260"]/*[@code="b"]'),
37         pubdate => xptext($xml,'*[@tag="260"]/*[@code="c"]'),
38         edition => xptext($xml,'*[@tag="250"]/*[@code="a"]'),
39     };
40 }
41
42 sub unapi {
43     my @recs = @_;
44     my $start = time();
45
46     my $ses1 = OpenSRF::AppSession->create('open-ils.cstore');
47     my $ses2 = OpenSRF::AppSession->create('open-ils.cstore');
48     my $ses3 = OpenSRF::AppSession->create('open-ils.cstore');
49     my ($req1, $req2, $req3);
50
51     my %records;
52     while(@recs) {
53         my ($id1, $id2, $id3) = (pop @recs, pop @recs, pop @recs);
54
55         for my $r ($req1, $req2, $req3) {
56             if($r) {
57                 my $data = $r->gather(1);
58                 my $xml = XML::LibXML->new->parse_string($data->{'unapi.bre'});
59                 $xml = $xml->documentElement;
60                 my $attrs = get_bib_attrs($xml);
61                 my $rec_id =  xptext($xml,'*[@tag="901"]/*[@code="c"]');
62                 $records{$rec_id}{$_} = $attrs->{$_} for keys %$attrs;
63
64                 my $rvols = [];
65                 for my $volnode ($xml->findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]')) {
66                     my $vol = {}; 
67                     $vol->{copies} = [];
68                     $vol->{label} = $volnode->getAttribute('label');
69                     for my $copynode ($volnode->getElementsByLocalName('copy')) {
70                         my $copy = {};   
71                         $copy->{barcode} = $copynode->getAttribute('barcode');
72                         push(@{$vol->{copies}}, $copy);
73                     }
74                     push(@{$records{$rec_id}->{volumes}}, $vol);
75                 }
76
77             }
78         }
79
80         $req1 = ($id1) ? $ses1->request('open-ils.cstore.json_query', {from => ['unapi.bre', $id1, 'marcxml', 'record', '{holdings_xml,acp}', 'CONS']}) : undef;
81         $req2 = ($id2) ? $ses1->request('open-ils.cstore.json_query', {from => ['unapi.bre', $id2, 'marcxml', 'record', '{holdings_xml,acp}', 'CONS']}) : undef;
82         $req3 = ($id3) ? $ses1->request('open-ils.cstore.json_query', {from => ['unapi.bre', $id3, 'marcxml', 'record', '{holdings_xml,acp}', 'CONS']}) : undef;
83     }
84
85
86     for my $r ($req1, $req2, $req3) {
87         if($r) {
88             my $data = $r->gather(1);
89             my $xml = XML::LibXML->new->parse_string($data->{'unapi.bre'});
90             $xml = $xml->documentElement;
91             my $attrs = get_bib_attrs($xml);
92             my $rec_id =  xptext($xml,'*[@tag="901"]/*[@code="c"]');
93             $records{$rec_id}{$_} = $attrs->{$_} for keys %$attrs;
94
95             my $rvols = [];
96             for my $volnode ($xml->findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]')) {
97                 my $vol = {}; 
98                 $vol->{copies} = [];
99                 $vol->{label} = $volnode->getAttribute('label');
100                 for my $copynode ($volnode->getElementsByLocalName('copy')) {
101                     my $copy = {};   
102                     $copy->{barcode} = $copynode->getAttribute('barcode');
103                     push(@{$vol->{copies}}, $copy);
104                 }
105                 push(@{$records{$rec_id}->{volumes}}, $vol);
106             }
107
108         }
109     }
110
111     my $duration = time() - $start;
112
113     for my $rec_id (keys %records) {
114         my $rec = $records{$rec_id};
115         print sprintf("%d [%s] has %d volumes and %d copies\n",
116             $rec_id, $rec->{title}, 
117             scalar(@{$rec->{volumes}}),
118             scalar(map { @{$_->{copies}} } @{$rec->{volumes}}));
119     }
120
121     #note, unapi.biblio_record_entry_feed per record performs the same as unapi.bre pre record
122     print "\nunapi 'unapi.bre' duration is $duration\n\n";
123 }
124
125 sub unapi_spread {
126     my @recs = @_;
127     my %records;
128     my $start = time();
129
130     my @reqs;
131     for my $rec_id (@recs) {
132
133         my $ses = OpenSRF::AppSession->create('open-ils.cstore');
134         my $req = $ses->request(
135             'open-ils.cstore.json_query', 
136             {from => ['unapi.bre', $rec_id, 'marcxml', 'record', '{holdings_xml,acp}', 'CONS']});
137
138         push(@reqs, $req);
139     }
140
141     for my $req (@reqs) {
142
143         my $data = $req->gather(1);
144         my $xml = XML::LibXML->new->parse_string($data->{'unapi.bre'});
145         $xml = $xml->documentElement;
146         my $attrs = get_bib_attrs($xml);
147         my $rec_id =  xptext($xml,'*[@tag="901"]/*[@code="c"]');
148         $records{$rec_id}{$_} = $attrs->{$_} for keys %$attrs;
149
150         my $rvols = [];
151         for my $volnode ($xml->findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]')) {
152             my $vol = {}; 
153             $vol->{copies} = [];
154             $vol->{label} = $volnode->getAttribute('label');
155             for my $copynode ($volnode->getElementsByLocalName('copy')) {
156                 my $copy = {};   
157                 $copy->{barcode} = $copynode->getAttribute('barcode');
158                 push(@{$vol->{copies}}, $copy);
159             }
160             push(@{$records{$rec_id}->{volumes}}, $vol);
161         }
162     }
163
164     my $duration = time() - $start;
165
166     for my $rec_id (keys %records) {
167         my $rec = $records{$rec_id};
168         print sprintf("%d [%s] has %d volumes and %d copies\n",
169             $rec_id, $rec->{title}, 
170             scalar(@{$rec->{volumes}}),
171             scalar(map { @{$_->{copies}} } @{$rec->{volumes}}));
172     }
173
174     #note, unapi.biblio_record_entry_feed per record performs the same as unapi.bre pre record
175     print "\nunapi 'unapi.bre' spread duration is $duration\n\n";
176 }
177
178
179
180 sub unapi_batch {
181     my @recs = @_;
182     my $start = time();
183
184     my $data = $e->json_query({from => ['unapi.biblio_record_entry_feed', "{".join(',',@recs)."}", 'marcxml', '{holdings_xml,acp}', 'CONS']})->[0];
185     my $xml = XML::LibXML->new->parse_string($data->{'unapi.biblio_record_entry_feed'});
186
187     my %records;
188     for my $rec_xml ($xml->documentElement->getElementsByLocalName('record')) { 
189
190         my $attrs = get_bib_attrs($rec_xml);
191         my $rec_id =  xptext($rec_xml,'*[@tag="901"]/*[@code="c"]');
192         #print "REC = $rec_xml : $rec_id : " . $attrs->{title} . "\n" . $rec_xml->toString . "\n";
193         $records{$rec_id}{$_} = $attrs->{$_} for keys %$attrs;
194
195         my $rvols = [];
196         for my $volnode ($rec_xml->findnodes('//*[local-name()="volumes"]/*[local-name()="volume"]')) {
197             my $vol = {}; 
198             $vol->{copies} = [];
199             $vol->{label} = $volnode->getAttribute('label');
200             for my $copynode ($volnode->getElementsByLocalName('copy')) {
201                 my $copy = {};   
202                 $copy->{barcode} = $copynode->getAttribute('barcode');
203                 push(@{$vol->{copies}}, $copy);
204             }
205             push(@{$records{$rec_id}->{volumes}}, $vol);
206         }
207     }
208
209     my $duration = time() - $start;
210
211     for my $rec_id (keys %records) {
212         my $rec = $records{$rec_id};
213         print sprintf("%d [%s] has %d volumes and %d copies\n",
214             $rec_id, $rec->{title}, 
215             scalar(@{$rec->{volumes}}),
216             scalar(map { @{$_->{copies}} } @{$rec->{volumes}}));
217     }
218     print "\nunapi 'batch feed' duration is $duration\n\n";
219 }
220
221 sub direct_spread {
222     my @recs = @_;
223     my %records;
224     my $start = time();
225
226     my $query = {
227         flesh => 4, 
228         flesh_fields => {
229             bre => ['call_numbers'], 
230             acn => ['copies', 'uris'], 
231             acp => ['location', 'stat_cat_entries', 'parts'],
232             ascecm => ['stat_cat', 'stat_cat_entry'],
233             acpm => ['part']
234         }
235     };
236
237     my @reqs;
238     for my $rec_id (@recs) {
239         my $ses = OpenSRF::AppSession->create('open-ils.cstore');
240         my $req = $ses->request(
241             'open-ils.cstore.direct.biblio.record_entry.search', {id => $rec_id}, $query);
242         push(@reqs, $req);
243     }
244
245     $records{$_}{counts} = $e->json_query({from => ['asset.record_copy_count', 1, $_, 0]})->[0] for @recs;
246     for my $req (@reqs) {
247         my $bre = $req->gather(1);
248         my $xml = XML::LibXML->new->parse_string($bre->marc)->documentElement;
249         my $attrs = get_bib_attrs($xml);
250         $records{$bre->id}{record} = $bre;
251         $records{$bre->id}{$_} = $attrs->{$_} for keys %$attrs;
252     }
253
254     my $duration = time() - $start;
255
256     for my $rec_id (keys %records) {
257         my $rec = $records{$rec_id};
258         print sprintf("%d [%s] has %d volumes and %d copies\n",
259             $rec_id, $rec->{title}, 
260             scalar(@{$rec->{record}->call_numbers}), 
261             scalar(map { @{$_->copies} } @{$rec->{record}->call_numbers}));
262     }
263
264     print "\n'direct' spread calls processing duration is $duration\n\n";
265 }
266
267
268 sub direct {
269     my @recs = @_;
270     my %records;
271
272     my $start = time();
273
274     my $ses1 = OpenSRF::AppSession->create('open-ils.cstore');
275     my $ses2 = OpenSRF::AppSession->create('open-ils.cstore');
276     my $ses3 = OpenSRF::AppSession->create('open-ils.cstore');
277     my ($req1, $req2, $req3);
278
279     my $query = {
280         flesh => 5, 
281         flesh_fields => {
282             bre => ['call_numbers'], 
283             acn => ['copies', 'uris'], 
284             acp => ['location', 'stat_cat_entries', 'parts'],
285             ascecm => ['stat_cat', 'stat_cat_entry'],
286             acpm => ['part']
287         }
288     };
289
290     my $first = 1;
291     while(@recs) {
292         my ($id1, $id2, $id3) = (pop @recs, pop @recs, pop @recs);
293
294         for my $r ($req1, $req2, $req3) {
295             last unless $r;
296             my $bre = $r->gather(1);
297             my $xml = XML::LibXML->new->parse_string($bre->marc)->documentElement;
298             my $attrs = get_bib_attrs($xml);
299             $records{$bre->id}{record} = $bre;
300             $records{$bre->id}{$_} = $attrs->{$_} for keys %$attrs;
301         }
302
303         $req1 = ($id1) ? $ses1->request('open-ils.cstore.direct.biblio.record_entry.search', {id => $id1}, $query) : undef;
304         $req2 = ($id2) ? $ses1->request('open-ils.cstore.direct.biblio.record_entry.search', {id => $id2}, $query) : undef;
305         $req3 = ($id3) ? $ses1->request('open-ils.cstore.direct.biblio.record_entry.search', {id => $id3}, $query) : undef;
306         
307         if($first) {
308             $records{$_}{counts} = $e->json_query({from => ['asset.record_copy_count', 1, $_, 0]})->[0] for @recs;
309             $first = 0;
310         }
311     }
312
313     for my $r ($req1, $req2, $req3) {
314         last unless $r;
315         my $bre = $r->gather(1);
316         my $xml = XML::LibXML->new->parse_string($bre->marc)->documentElement;
317         my $attrs = get_bib_attrs($xml);
318         $records{$bre->id}{record} = $bre;
319         $records{$bre->id}{$_} = $attrs->{$_} for keys %$attrs;
320     }
321
322
323     my $duration = time() - $start;
324
325     for my $rec_id (keys %records) {
326         my $rec = $records{$rec_id};
327         print sprintf("%d [%s] has %d volumes and %d copies\n",
328             $rec_id, $rec->{title}, 
329             scalar(@{$rec->{record}->call_numbers}), 
330             scalar(map { @{$_->copies} } @{$rec->{record}->call_numbers}));
331     }
332
333     print "\n'direct' calls processing duration is $duration\n\n";
334 }
335
336 for (0..1) { direct(@recs); unapi(@recs); unapi_batch(@recs); unapi_spread(@recs); direct_spread(@recs); }