View | Details | Raw Unified | Return to bug 6557
Collapse All | Expand All

(-)a/misc/cronjobs/crontab.example (+3 lines)
Lines 67-72 KOHA_CRON_PATH = /usr/share/koha/bin/cronjobs Link Here
67
# Cancel expired holds
67
# Cancel expired holds
68
0 1 * * *  $KOHA_CRON_PATH/holds/cancel_expired_holds.pl >/dev/null 2>&1
68
0 1 * * *  $KOHA_CRON_PATH/holds/cancel_expired_holds.pl >/dev/null 2>&1
69
69
70
# Update popularity counts for biblio records
71
0 2 * * *  $KOHA_CRON_PATH/update_totalissues.pl --commit=1000 --use-stats --incremental --interval=1d >/dev/null 2>&1
72
70
# ZEBRA INDEX UPDATES with -z option, incremental index updates throughout the day
73
# ZEBRA INDEX UPDATES with -z option, incremental index updates throughout the day
71
# for both authorities and bibs
74
# for both authorities and bibs
72
*/10 * * * *  $KOHA_CRON_PATH/../migration_tools/rebuild_zebra.pl -b -a -z >/dev/null
75
*/10 * * * *  $KOHA_CRON_PATH/../migration_tools/rebuild_zebra.pl -b -a -z >/dev/null
(-)a/misc/cronjobs/update_totalissues.pl (-1 / +297 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright 2012 C & P Bibliography Services
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 2 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use strict;
21
use warnings;
22
23
BEGIN {
24
25
    # find Koha's Perl modules
26
    # test carefully before changing this
27
    use FindBin;
28
    eval { require "$FindBin::Bin/../kohalib.pl" };
29
}
30
31
use Getopt::Long;
32
use Pod::Usage;
33
use C4::Context;
34
use C4::Biblio;
35
use DateTime;
36
use DateTime::Format::MySQL;
37
use Time::HiRes qw/time/;
38
use POSIX qw/strftime ceil/;
39
40
sub usage {
41
    pod2usage( -verbose => 2 );
42
    exit;
43
}
44
45
$| = 1;
46
47
# command-line parameters
48
my $verbose   = 0;
49
my $test_only = 0;
50
my $want_help = 0;
51
my $since;
52
my $interval;
53
my $usestats    = 0;
54
my $useitems    = 0;
55
my $incremental = 0;
56
my $commit      = 100;
57
my $unit;
58
59
my $result = GetOptions(
60
    'v|verbose'    => \$verbose,
61
    't|test'       => \$test_only,
62
    's|since=s'    => \$since,
63
    'i|interval=s' => \$interval,
64
    'use-stats'    => \$usestats,
65
    'use-items'    => \$useitems,
66
    'incremental'  => \$incremental,
67
    'c|commit=i'   => \$commit,
68
    'h|help'       => \$want_help
69
);
70
71
binmode( STDOUT, ":utf8" );
72
73
if ( defined $since && defined $interval ) {
74
    print "The --since and --interval options are mutually exclusive.\n\n";
75
    $want_help = 1;
76
}
77
78
if ( $useitems && $incremental ) {
79
    print
80
      "The --use-items and --incremental options are mutually exclusive.\n\n";
81
    $want_help = 1;
82
}
83
84
if ( $incremental && !( defined $since || defined $interval ) ) {
85
    $interval = '24h';
86
}
87
88
unless ( $usestats || $useitems ) {
89
    print "You must specify either --use-stats and/or --use-items.\n\n";
90
    $want_help = 1;
91
}
92
93
if ( not $result or $want_help ) {
94
    usage();
95
}
96
97
my $dbh = C4::Context->dbh;
98
$dbh->{AutoCommit} = 0;
99
100
my $num_bibs_processed = 0;
101
102
my $starttime = time();
103
104
process_items() if $useitems;
105
process_stats() if $usestats;
106
107
report();
108
109
exit 0;
110
111
sub process_items {
112
    my $query =
113
"SELECT items.biblionumber, SUM(items.issues) FROM items GROUP BY items.biblionumber;";
114
    process_query($query);
115
}
116
117
sub process_stats {
118
    if ($interval) {
119
        my $dt = DateTime->now;
120
121
        my %units = (
122
            h => 'hours',
123
            d => 'days',
124
            w => 'weeks',
125
            m => 'months',
126
            y => 'years'
127
        );
128
129
        $interval =~ m/([0-9]*)([hdwmy]?)$/;
130
        $unit = $2 || 'd';
131
        $since = DateTime::Format::MySQL->format_datetime(
132
            $dt->subtract( $units{$unit} => $1 ) );
133
    }
134
    my $limit = '';
135
    $limit = " AND statistics.datetime >= ?" if ( $interval || $since );
136
137
    my $query =
138
"SELECT biblio.biblionumber, COUNT(statistics.itemnumber) FROM biblio LEFT JOIN items ON (biblio.biblionumber=items.biblionumber) LEFT JOIN statistics ON (items.itemnumber=statistics.itemnumber) WHERE statistics.type = 'issue' $limit GROUP BY biblio.biblionumber;";
139
    process_query( $query, $limit );
140
141
    unless ($incremental) {
142
        $query =
143
"SELECT biblio.biblionumber, 0 FROM biblio LEFT JOIN items ON (biblio.biblionumber=items.biblionumber) LEFT JOIN statistics ON (items.itemnumber=statistics.itemnumber) WHERE statistics.itemnumber IS NULL GROUP BY biblio.biblionumber;";
144
        process_query( $query, '' );
145
146
        $query =
147
"SELECT biblio.biblionumber, 0 FROM biblio LEFT JOIN items ON (biblio.biblionumber=items.biblionumber) WHERE items.itemnumber IS NULL GROUP BY biblio.biblionumber;";
148
        process_query( $query, '' );
149
    }
150
151
    $dbh->commit();
152
}
153
154
sub process_query {
155
    my $query    = shift;
156
    my $uselimit = shift;
157
    my $sth      = $dbh->prepare($query);
158
159
    if ( $since && $uselimit ) {
160
        $sth->execute($since);
161
    }
162
    else {
163
        $sth->execute();
164
    }
165
166
    while ( my ( $biblionumber, $totalissues ) = $sth->fetchrow_array() ) {
167
        $num_bibs_processed++;
168
        $totalissues = 0 unless $totalissues;
169
        print "Processing bib $biblionumber ($totalissues issues)\n"
170
          if $verbose;
171
        if ( not $test_only ) {
172
            if ( $incremental && $totalissues > 0 ) {
173
                UpdateTotalIssues( $biblionumber, $totalissues );
174
            }
175
            else {
176
                UpdateTotalIssues( $biblionumber, 0, $totalissues );
177
            }
178
        }
179
        if ( not $test_only and ( $num_bibs_processed % $commit ) == 0 ) {
180
            print_progress_and_commit($num_bibs_processed);
181
        }
182
    }
183
184
    $dbh->commit();
185
}
186
187
sub report {
188
    my $endtime = time();
189
    my $totaltime = ceil( ( $endtime - $starttime ) * 1000 );
190
    $starttime = strftime( '%D %T', localtime($starttime) );
191
    $endtime   = strftime( '%D %T', localtime($endtime) );
192
193
    my $summary = <<_SUMMARY_;
194
195
Update total issues count script report
196
=======================================================
197
Run started at:                         $starttime
198
Run ended at:                           $endtime
199
Total run time:                         $totaltime ms
200
Number of bibs modified:                $num_bibs_processed
201
_SUMMARY_
202
    $summary .= "\n****  Ran in test mode only  ****\n" if $test_only;
203
    print $summary;
204
}
205
206
sub print_progress_and_commit {
207
    my $recs = shift;
208
    $dbh->commit();
209
    print "... processed $recs records\n";
210
}
211
212
=head1 NAME
213
214
update_totalissues.pl
215
216
=head1 SYNOPSIS
217
218
  update_totalissues.pl --use-stats
219
  update_totalissues.pl --use-items
220
  update_totalissues.pl --commit=1000
221
  update_totalissues.pl --since='2012-01-01'
222
  update_totalissues.pl --interval=30d
223
224
=head1 DESCRIPTION
225
226
This batch job populates bibliographic records' total issues count based
227
on historical issue statistics.
228
229
=over 8
230
231
=item B<--help>
232
233
Prints this help
234
235
=item B<-v|--verbose>
236
237
Provide verbose log information (list every bib modified).
238
239
=item B<--use-stats>
240
241
Use the data in the statistics table for populating total issues.
242
243
=item B<--use-items>
244
245
Use items.issues data for populating total issues. Note that issues
246
data from the items table does not respect the --since or --interval
247
options, by definition. Also note that if both --use-stats and
248
--use-items are specified, the count of biblios processed will be
249
misleading.
250
251
=item B<-s|--since=DATE>
252
253
Only process issues recorded in the statistics table since DATE.
254
255
=item B<-i|--interval=S>
256
257
Only process issues recorded in the statistics table in the last N
258
units of time. The interval should consist of a number with a one-letter
259
unit suffix. The valid suffixes are h (hours), d (days), w (weeks),
260
m (months), and y (years). The default unit is days.
261
262
=item B<--incremental>
263
264
Add the number of issues found in the statistics table to the existing
265
total issues count. Intended so that this script can be used as a cron
266
job to update popularity information during low-usage periods. If neither
267
--since or --interval are specified, incremental mode will default to
268
processing the last twenty-four hours.
269
270
=item B<--commit=N>
271
272
Commit the results to the database after every N records are processed.
273
274
=item B<--test>
275
276
Only test the popularity population script.
277
278
=back
279
280
=head1 WARNING
281
282
If the time on your database server does not match the time on your Koha
283
server you will need to take that into account, and probably use the
284
--since argument instead of the --interval argument for incremental 
285
updating.
286
287
=head1 CREDITS
288
289
This patch to Koha was sponsored by the Arcadia Public Library and the
290
Arcadia Public Library Foundation in honor of Jackie Faust-Moreno, late
291
director of the Arcadia Public Library.
292
293
=head1 AUTHOR
294
295
Jared Camins-Esakov <jcamins AT cpbibliography DOT com>
296
297
=cut

Return to bug 6557