Frédéric Demians
dcfa31d5dc
Bug 11395 uses the session to store the report sent to the interface (update on biblio XX OK, etc.). If the session is stored in mysql, the max size of the sessions.a_session will be reached easily (TEXT field). To reproduce: 0/ Set SessionStorage to 'mysql' 1/ Create a file with 500 biblionumbers: mysql -e "select biblionumber from biblio limit 500;" | tail -n 500 > /tmp/biblionumbers.txt 2/ Define a marc modification template (something like "delete field 99$9" is nice) 3/ Load the /tmp/biblionumbers.txt in the batch biblio modification tool 4/ Repeat 3 You will get: Syck parser (line 1534, column 6): syntax error at /usr/lib/i386-linux-gnu/perl5/5.20/YAML/Syck.pm line 75. None Koha page is reachable. It comes from get_template_and_user > checkauth > get_session > l.1595 $session = new CGI::Session("driver:MySQL;serializer:yaml;id:md5", $sessionID, {Handle=>$dbh}); 5/ Get your sessionID contained in your CGISESSID cookie Have a look at the value a_session in the sessions table: mysql> select a_session from sessions where id="YOUR_SESSIONID"; You should see that the yaml is not correctly ended. The size of the DB field has been reached and the yaml is truncated. Test plan: 0/ Delete your CGISESSID cookie 1/ Try to reproduce the previous issue 2/ After the second batch, have a look at the sessions table and confirm that only one job_$JOB_ID exist in the yaml Signed-off-by: Jonathan Druart <jonathan.druart@biblibre.com> NOTE: Nicely clears batch job session information. (2) is incorrect. This cleans up after a full run. Signed-off-by: Mark Tompsett <mtompset@hotmail.com> Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
263 lines
8.1 KiB
Perl
Executable file
263 lines
8.1 KiB
Perl
Executable file
#!/usr/bin/perl
|
|
|
|
# This file is part of Koha.
|
|
#
|
|
# Copyright 2013 BibLibre
|
|
#
|
|
# Koha is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as
|
|
# published by the Free Software Foundation; either version 3
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# Koha is distributed in the hope that it will be useful, but
|
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General
|
|
# Public License along with Koha; if not, see
|
|
# <http://www.gnu.org/licenses>
|
|
|
|
use Modern::Perl;
|
|
|
|
use CGI;
|
|
use List::MoreUtils qw( uniq );
|
|
|
|
use C4::Auth qw( get_template_and_user );
|
|
use C4::Output qw( output_html_with_http_headers );
|
|
use C4::AuthoritiesMarc qw( BuildSummary GetAuthTypeCode ModAuthority );
|
|
use C4::BackgroundJob;
|
|
use C4::Biblio qw( GetMarcBiblio ModBiblio );
|
|
use C4::MarcModificationTemplates qw( GetModificationTemplateActions GetModificationTemplates ModifyRecordWithTemplate );
|
|
use Koha::Authority;
|
|
|
|
my $input = new CGI;
|
|
our $dbh = C4::Context->dbh;
|
|
my $op = $input->param('op') // q|form|;
|
|
my $recordtype = $input->param('recordtype') // 'biblio';
|
|
my $mmtid = $input->param('marc_modification_template_id');
|
|
|
|
my ( @messages );
|
|
|
|
my ( $template, $loggedinuser, $cookie ) = get_template_and_user({
|
|
template_name => 'tools/batch_record_modification.tt',
|
|
query => $input,
|
|
type => "intranet",
|
|
authnotrequired => 0,
|
|
flagsrequired => { tools => 'biblio_batchmod' },
|
|
});
|
|
|
|
|
|
my $sessionID = $input->cookie("CGISESSID");
|
|
|
|
my $runinbackground = $input->param('runinbackground');
|
|
my $completedJobID = $input->param('completedJobID');
|
|
if ( $completedJobID ) {
|
|
my $job = C4::BackgroundJob->fetch($sessionID, $completedJobID);
|
|
my $report = $job->get('report');
|
|
my $messages = $job->get('messages');
|
|
$template->param(
|
|
report => $report,
|
|
messages => $messages,
|
|
view => 'report',
|
|
);
|
|
output_html_with_http_headers $input, $cookie, $template->output;
|
|
$job->clear();
|
|
exit;
|
|
}
|
|
|
|
my @templates = GetModificationTemplates( $mmtid );
|
|
unless ( @templates ) {
|
|
$op = 'error';
|
|
$template->param(
|
|
view => 'errors',
|
|
errors => ['no_template_defined'],
|
|
);
|
|
output_html_with_http_headers $input, $cookie, $template->output;
|
|
exit;
|
|
}
|
|
|
|
if ( $mmtid ) {
|
|
my @actions = GetModificationTemplateActions( $mmtid );
|
|
unless ( @actions ) {
|
|
$op = 'form';
|
|
push @messages, {
|
|
type => 'error',
|
|
code => 'no_action_defined_for_the_template',
|
|
mmtid => $mmtid,
|
|
};
|
|
}
|
|
}
|
|
|
|
if ( $op eq 'form' ) {
|
|
# Display the form
|
|
$template->param(
|
|
view => 'form',
|
|
);
|
|
} elsif ( $op eq 'list' ) {
|
|
# List all records to process
|
|
my ( @records, @record_ids );
|
|
if ( my $bib_list = $input->param('bib_list') ) {
|
|
# Come from the basket
|
|
@record_ids = split /\//, $bib_list;
|
|
$recordtype = 'biblio';
|
|
} elsif ( my $uploadfile = $input->param('uploadfile') ) {
|
|
# A file of id is given
|
|
while ( my $content = <$uploadfile> ) {
|
|
next unless $content;
|
|
$content =~ s/[\r\n]*$//;
|
|
push @record_ids, $content if $content;
|
|
}
|
|
} else {
|
|
# The user enters manually the list of id
|
|
push @record_ids, split( /\s\n/, $input->param('recordnumber_list') );
|
|
}
|
|
|
|
for my $record_id ( uniq @record_ids ) {
|
|
if ( $recordtype eq 'biblio' ) {
|
|
# Retrieve biblio information
|
|
my $biblio = C4::Biblio::GetBiblio( $record_id );
|
|
unless ( $biblio ) {
|
|
push @messages, {
|
|
type => 'warning',
|
|
code => 'biblio_not_exists',
|
|
biblionumber => $record_id,
|
|
};
|
|
next;
|
|
}
|
|
push @records, $biblio;
|
|
} else {
|
|
# Retrieve authority information
|
|
my $authority = Koha::Authority->get_from_authid( $record_id );
|
|
unless ( $authority ) {
|
|
push @messages, {
|
|
type => 'warning',
|
|
code => 'authority_not_exists',
|
|
authid => $record_id,
|
|
};
|
|
next;
|
|
}
|
|
|
|
push @records, {
|
|
authid => $record_id,
|
|
summary => C4::AuthoritiesMarc::BuildSummary( $authority->record, $record_id ),
|
|
};
|
|
}
|
|
}
|
|
$template->param(
|
|
records => \@records,
|
|
mmtid => $mmtid,
|
|
view => 'list',
|
|
);
|
|
} elsif ( $op eq 'modify' ) {
|
|
# We want to modify selected records!
|
|
my @record_ids = $input->param('record_id');
|
|
|
|
my ( $job );
|
|
if ( $runinbackground ) {
|
|
my $job_size = scalar( @record_ids );
|
|
$job = C4::BackgroundJob->new( $sessionID, "FIXME", $ENV{SCRIPT_NAME}, $job_size );
|
|
my $job_id = $job->id;
|
|
if (my $pid = fork) {
|
|
$dbh->{InactiveDestroy} = 1;
|
|
|
|
my $reply = CGI->new("");
|
|
print $reply->header(-type => 'text/html');
|
|
print '{"jobID":"' . $job_id . '"}';
|
|
exit 0;
|
|
} elsif (defined $pid) {
|
|
close STDOUT;
|
|
close STDERR;
|
|
} else {
|
|
warn "fork failed while attempting to run $ENV{'SCRIPT_NAME'} as a background job";
|
|
exit 0;
|
|
}
|
|
}
|
|
|
|
my $report = {
|
|
total_records => 0,
|
|
total_success => 0,
|
|
};
|
|
my $progress = 0;
|
|
$dbh->{RaiseError} = 1;
|
|
RECORD_IDS: for my $record_id ( sort { $a <=> $b } @record_ids ) {
|
|
$report->{total_records}++;
|
|
next unless $record_id;
|
|
|
|
if ( $recordtype eq 'biblio' ) {
|
|
# Biblios
|
|
my $biblionumber = $record_id;
|
|
|
|
# Finally, modify the biblio
|
|
my $error = eval {
|
|
my $record = GetMarcBiblio( $biblionumber );
|
|
ModifyRecordWithTemplate( $mmtid, $record );
|
|
ModBiblio( $record, $biblionumber );
|
|
};
|
|
if ( $error and $error != 1 or $@ ) { # ModBiblio returns 1 if everything as gone well
|
|
push @messages, {
|
|
type => 'error',
|
|
code => 'biblio_not_modified',
|
|
biblionumber => $biblionumber,
|
|
error => ($@ ? $@ : $error),
|
|
};
|
|
} else {
|
|
push @messages, {
|
|
type => 'success',
|
|
code => 'biblio_modified',
|
|
biblionumber => $biblionumber,
|
|
};
|
|
$report->{total_success}++;
|
|
}
|
|
} else {
|
|
# Authorities
|
|
my $authid = $record_id;
|
|
my $error = eval {
|
|
my $authority = Koha::Authority->get_from_authid( $authid );
|
|
my $record = $authority->record;
|
|
ModifyRecordWithTemplate( $mmtid, $record );
|
|
ModAuthority( $authid, $record, GetAuthTypeCode( $authid ) );
|
|
};
|
|
if ( $error and $error != $authid or $@ ) {
|
|
push @messages, {
|
|
type => 'error',
|
|
code => 'authority_not_modified',
|
|
authid => $authid,
|
|
error => ($@ ? $@ : 0),
|
|
};
|
|
} else {
|
|
push @messages, {
|
|
type => 'success',
|
|
code => 'authority_modified',
|
|
authid => $authid,
|
|
};
|
|
$report->{total_success}++;
|
|
}
|
|
}
|
|
|
|
$job->set({
|
|
view => 'report',
|
|
report => $report,
|
|
messages => \@messages,
|
|
});
|
|
$job->progress( ++$progress ) if $runinbackground;
|
|
}
|
|
|
|
if ($runinbackground) {
|
|
$job->finish if defined $job;
|
|
} else {
|
|
$template->param(
|
|
view => 'report',
|
|
report => $report,
|
|
messages => \@messages,
|
|
);
|
|
}
|
|
}
|
|
|
|
$template->param(
|
|
messages => \@messages,
|
|
recordtype => $recordtype,
|
|
MarcModificationTemplatesLoop => \@templates,
|
|
);
|
|
|
|
output_html_with_http_headers $input, $cookie, $template->output;
|