Bug 8746: rebuild_zebra_sliced.sh now export/index records as MARCXML
[koha.git] / misc / migration_tools / rebuild_zebra_sliced.sh
1 #!/bin/sh
2
3 usage() {
4     local scriptname=$(basename $0)
5     cat <<EOF
6 $scriptname
7
8 Index Koha records by chunks. It is useful when a record causes errors and
9 stops the indexing process. With this script, if indexing of one chunk fails,
10 that chunk is split into two or more chunks, and indexing continues on these chunks.
11 rebuild_zebra.pl is called only once to export records. Splitting and indexing
12 is handled by this script (using yaz-marcdump and zebraidx).
13
14 Usage:
15 $scriptname [-t type] [-l X] [-o X] [-s X] [-d /export/dir] [-L /log/dir] [-r] [-f] [--reset-index]
16 $scriptname -h
17
18     -o | --offset         Offset parameter of rebuild_zebra.pl.
19                           Default: $OFFSET
20     -l | --length         Length parameter of rebuild_zebra.pl. If omitted, the
21                           length is automatically calculated to index all
22                           records
23     -s | --chunks-size    Initial chunk size (number of records indexed at once)
24                           Default: $CHUNKSSIZE
25     -d | --export-dir     Where rebuild_zebra.pl will export data
26                           Default: $EXPORTDIR
27     -L | --log-dir        Log directory
28                           Default: $LOGDIR
29     -r | --remove-logs    Clean log directory before start
30                           Default: $RMLOGS
31     -t | --type           Record type ('biblios' or 'authorities')
32                           Default: $TYPE
33     -f | --force          Don't ask for confirmation before start
34     -h | --help           Display this help message
35     --reset-index         Reset Zebra index for 'type'
36 EOF
37 }
38
39 splitfile() {
40     local file=$1
41     local prefix=$2
42     local size=$3
43     local script='
44         my $prefix = '"\"$prefix\""';
45         my $size = '"$size"';
46         my ($i,$count) = (0,0);
47         open(my $fh, "<", '"\"$file\""');
48         open(my $out, ">", sprintf("$prefix%02d", $i));
49         my $closed = 0;
50         while (<$fh>) {
51             my $line = $_;
52             if ($closed) {
53                 open($out, ">", sprintf("$prefix%02d", $i));
54                 $closed = 0;
55             }
56             print $out $line;
57             $count++ if ($line =~ m|^</record>|);
58             if ($count == $size) {
59                 $count = 0;
60                 $i++;
61                 close($out);
62                 $closed = 1;
63             }
64         }
65     '
66     $PERL -e "$script"
67 }
68
69 indexfile() {
70     local file=$1
71     local chunkssize=$2
72
73     if [ $chunkssize -lt 1 ]; then
74         echo "Fail on file $file"
75     else
76
77         local prefix="${file}_${chunkssize}_"
78         echo "Splitting file in chunks of $chunkssize records"
79         splitfile $file $prefix $chunkssize
80
81         dir=$(dirname $prefix)
82         local files="$(find $dir -regex $prefix[0-9]+ | sort | tr '\n' ' ')"
83         for chunkfile in $files; do
84             echo "Indexing $chunkfile"
85             size=$(grep '^</record>' $chunkfile | wc -l)
86             logfile="$LOGDIR/zebraidx.$(basename $chunkfile).log"
87             ZEBRAIDX_CMD="$ZEBRAIDX -c $CONFIGFILE -d $TYPE -g marcxml update $chunkfile"
88             $ZEBRAIDX_CMD >$logfile 2>&1
89             grep "Records: $size" $logfile >/dev/null 2>&1
90             if [ $? -ne 0 ]; then
91                 echo "Indexing failed. Split file and continue..."
92                 indexfile $chunkfile $(($chunkssize/2))
93             else
94                 ZEBRAIDX_CMD="$ZEBRAIDX -c $CONFIGFILE -d $TYPE -g marcxml commit"
95                 $ZEBRAIDX_CMD >> $logfile 2>&1
96             fi
97         done
98     fi
99 }
100
101 OFFSET=0
102 LENGTH=
103 CHUNKSSIZE=10000
104 EXPORTDIR=/tmp/rebuild/export
105 LOGDIR=/tmp/rebuild/logs
106 RMLOGS=no
107 NOCONFIRM=no
108 TYPE=biblios
109 HELP=no
110 RESETINDEX=no
111
112 # Get parameters
113 while [ $1 ]; do
114     case $1 in
115         -o | --offset )
116             shift
117             OFFSET=$1
118             ;;
119         -l | --length )
120             shift
121             LENGTH=$1
122             ;;
123         -s | --chunks-size )
124             shift
125             CHUNKSSIZE=$1
126             ;;
127         -d | --export-dir )
128             shift
129             EXPORTDIR=$1
130             ;;
131         -L | --log-dir )
132             shift
133             LOGDIR=$1
134             ;;
135         -r | --remove-logs )
136             RMLOGS=yes
137             ;;
138         -t | --type )
139             shift
140             TYPE=$1
141             ;;
142         -f | --force )
143             NOCONFIRM=yes
144             ;;
145         -h | --help )
146             HELP=yes
147             ;;
148         --reset-index )
149             RESETINDEX=yes
150             ;;
151         * )
152             usage
153             exit 1
154     esac
155     shift
156 done
157
158 if [ $HELP = "yes" ]; then
159     usage
160     exit 0
161 fi
162
163 if [ -z $KOHA_CONF ]; then
164     echo "KOHA_CONF is not set"
165     exit 1
166 fi
167
168 if [ -z $PERL5LIB ]; then
169     echo "PERL5LIB is not set"
170     exit 1
171 fi
172
173
174 TYPESWITCH=
175 SQLTABLE=
176 case $TYPE in
177     biblios )
178         TYPESWITCH=-b
179         SQLTABLE="biblio"
180         ;;
181     authorities )
182         TYPESWITCH=-a
183         SQLTABLE="auth_header"
184         ;;
185     * )
186         echo "'$TYPE' is an unknown type. Defaulting to 'biblios'"
187         TYPESWITCH=-b
188         TYPE=biblios
189         SQLTABLE="biblio"
190 esac
191
192 PERL=`which perl`
193 if [ -z $PERL ]; then
194     echo "perl not found"
195     exit 1
196 fi
197
198 if [ -z $LENGTH ]; then
199     LENGTH=$($PERL -e '
200         use C4::Context;
201         my ($count) = C4::Context->dbh->selectrow_array(qq{
202             SELECT COUNT(*) FROM '"$SQLTABLE"'
203         });
204         print $count;
205     ')
206 fi
207
208 ZEBRAIDX=`which zebraidx`
209 if [ -z $ZEBRAIDX ]; then
210     echo "zebraidx not found"
211     exit 1
212 fi
213
214 REBUILDZEBRA="`dirname $0`/rebuild_zebra.pl"
215 if [ ! -f $REBUILDZEBRA ]; then
216     echo "$REBUILDZEBRA: file not found"
217     exit 1
218 fi
219
220 echo ""
221 echo "Configuration"
222 echo "========================================================================="
223 echo "KOHA_CONF: $KOHA_CONF"
224 echo "PERL5LIB: $PERL5LIB"
225 echo "-------------------------------------------------------------------------"
226 echo "Start at offset: $OFFSET"
227 echo "Total number of records to index: $LENGTH"
228 echo "Initial chunk size: $CHUNKSSIZE"
229 echo "Export directory: $EXPORTDIR"
230 echo "Log directory: $LOGDIR"
231 echo "Remove logs before start? $RMLOGS"
232 echo "Type of record: $TYPE"
233 echo "Reset index before start? $RESETINDEX"
234 echo "-------------------------------------------------------------------------"
235 echo "zebraidx path: $ZEBRAIDX"
236 echo "rebuild_zebra path: $REBUILDZEBRA"
237 echo "perl path: $PERL"
238 echo "========================================================================="
239
240 if [ $NOCONFIRM != "yes" ]; then
241     confirm=y
242     echo -n "Confirm ? [Y/n] "
243     read response
244     if [ $response ] && [ $response != "yes" ] && [ $response != "y" ]; then
245         confirm=n
246     fi
247
248     if [ $confirm = "n" ]; then
249         exit 0
250     fi
251 fi
252
253 mkdir -p $EXPORTDIR
254 if [ $? -ne 0 ]; then
255     echo "Failed to create directory $EXPORTDIR. Aborting."
256     exit 1
257 fi
258
259 mkdir -p $LOGDIR
260 if [ $? -ne 0 ]; then
261     echo "Failed to create directory $LOGDIR. Aborting."
262     exit 1
263 fi
264
265 if [ $RMLOGS = "yes" ]; then
266     rm -f $LOGDIR/*.log
267 fi
268
269 REBUILDZEBRA_CMD="$REBUILDZEBRA $TYPESWITCH -v -x -k -d $EXPORTDIR --offset $OFFSET --length $LENGTH --skip-index"
270 echo "\n$REBUILDZEBRA_CMD"
271 $REBUILDZEBRA_CMD
272
273 EXPORTFILE=
274 case $TYPE in
275     biblios )
276         EXPORTFILE="$EXPORTDIR/biblio/exported_records"
277         ;;
278     authorities )
279         EXPORTFILE="$EXPORTDIR/authority/exported_records"
280         ;;
281     * )
282         echo "Error: TYPE '$TYPE' is not supported"
283         exit 1
284 esac
285
286 CONFIGFILE="$(dirname $KOHA_CONF)/zebradb/zebra-$TYPE.cfg"
287
288 if [ $RESETINDEX = "yes" ]; then
289     RESETINDEX_CMD="$ZEBRAIDX -c $CONFIGFILE init"
290     echo "\n$RESETINDEX_CMD"
291     $RESETINDEX_CMD
292     echo ""
293 fi
294
295 indexfile $EXPORTFILE $CHUNKSSIZE