File Coverage

blib/lib/KSx/Index/ZlibDocWriter.pm
Criterion Covered Total %
statement 87 87 100.0
branch 14 20 70.0
condition 1 3 33.3
subroutine 15 15 100.0
pod 4 4 100.0
total 121 129 93.8


line stmt bran cond sub pod time code
1 2     2   6882400 use strict;
  2         8  
  2         189  
2              
3             package KSx::Index::ZlibDocWriter;
4 2     2   17 use base qw( KinoSearch::Index::DataWriter );
  2         5  
  2         1591  
5 2     2   17 use Carp;
  2         6  
  2         185  
6 2     2   15 use Scalar::Util qw( blessed );
  2         3  
  2         117  
7 2     2   100458 use Compress::Zlib qw( compress );
  2         2464251  
  2         212  
8 2     2   18 use KinoSearch::Util::StringHelper qw( cat_bytes );
  2         106  
  2         100  
9 2     2   13 use KinoSearch qw( to_perl );
  2         4  
  2         83  
10 2     2   11 use bytes;
  2         4  
  2         17  
11 2     2   51 no bytes;
  2         3  
  2         11  
12              
13             # Inside-out member vars.
14             our %ix_out;
15             our %dat_out;
16              
17             # Inherit constructor.
18              
19             sub _lazy_init {
20 4     4   8 my $self = shift;
21              
22             # Get outstreams. Skip past non-doc #0.
23 4         26 my $folder = $self->get_folder;
24 4         36 my $ix_file = $self->get_segment->get_name . "/zdocs.ix";
25 4         29 my $dat_file = $self->get_segment->get_name . "/zdocs.dat";
26 4 50       51 $ix_out{$$self} = $folder->open_out($ix_file)
27             or confess KinoSearch->error;
28 4 50       56 $dat_out{$$self} = $folder->open_out($dat_file)
29             or confess KinoSearch->error;
30 4         23 $ix_out{$$self}->write_i64(0);
31             }
32              
33             sub add_inverted_doc {
34 13     13 1 253646 my ( $self, %args ) = @_;
35 13 100       59 _lazy_init($self) unless $ix_out{$$self};
36 13         24 my $inverter = $args{inverter};
37 13         20 my $ix_out = $ix_out{$$self};
38 13         20 my $dat_out = $dat_out{$$self};
39              
40             # Check doc id.
41 13         53 my $expected = $ix_out->tell / 8;
42 13 50       168 confess("Expected doc id $expected, got '$args{doc_id}'")
43             unless $args{doc_id} == $expected;
44              
45 13         22 my $to_compress = "";
46 13         15 my $count = 0;
47 13         51 my $schema = $self->get_schema;
48 13         56 $inverter->iterate;
49 13         50 while ( $inverter->next ) {
50 52 100       289 next unless $inverter->get_type->stored;
51 39         130 my $name = $inverter->get_field_name;
52 39         117 my $value = $inverter->get_value;
53 39         110 cat_bytes( $to_compress, pack( "w", bytes::length($name) ) );
54 39         1392 cat_bytes( $to_compress, $name );
55 39         83 cat_bytes( $to_compress, pack( "w", bytes::length($value) ) );
56 39         173 cat_bytes( $to_compress, $value );
57 39         297 $count++;
58             }
59             # Prepend count of fields to store in this Doc.
60 13         32 $to_compress = pack( "w", $count ) . $to_compress;
61              
62             # Write file pointer to index file. Write compressed serialized string to
63             # main file.
64 13         57 $ix_out->write_i64( $dat_out->tell );
65 13         50 $dat_out->print( compress($to_compress) );
66             }
67              
68             sub add_segment {
69 3     3 1 16 my ( $self, %args ) = @_;
70 3         8 my $seg_reader = $args{reader};
71 3         6 my $doc_map = $args{doc_map};
72 3         26 my $doc_max = $seg_reader->doc_max;
73              
74             # Bail if the supplied segment is empty. */
75 3 50       13 return unless $doc_max;
76              
77 3 100       19 _lazy_init($self) unless $ix_out{$$self};
78 3         7 my $ix_out = $ix_out{$$self};
79 3         7 my $dat_out = $dat_out{$$self};
80 3         27 my $doc_reader = $seg_reader->obtain("KinoSearch::Index::DocReader");
81 3 50 33     45 confess("Not a ZlibDocReader")
82             unless ( blessed($doc_reader)
83             and $doc_reader->isa("KSx::Index::ZlibDocReader") );
84              
85 3         12 for ( my $i = 1; $i <= $doc_max; $i++ ) {
86 24 100       102 next unless $doc_map->get($i);
87 21         37 my $buf;
88 21         88 $doc_reader->read_record( $i, \$buf );
89 21         84 $ix_out->write_i64( $dat_out->tell );
90 21         6719 $dat_out->print($buf);
91             }
92             }
93              
94             sub finish {
95 4     4 1 426 my $self = shift;
96 4         17 my $ix_out = $ix_out{$$self};
97 4         11 my $dat_out = $dat_out{$$self};
98 4 50       20 if ($ix_out) {
99             # Write one extra file pointer so that we can always derive record
100             # length.
101 4         1919 $ix_out->write_i64( $dat_out->tell );
102              
103             # Close streams and store metadata.
104 4         32 $ix_out->close;
105 4         41 $dat_out->close;
106 4         28 my $segment = $self->get_segment;
107 4         73 $segment->store_metadata(
108             key => 'zdocs',
109             metadata => $self->metadata,
110             );
111             }
112             }
113              
114 4     4 1 195 sub format {1}
115              
116             sub DESTROY {
117 4     4   447 my $self = shift;
118 4         28 delete $ix_out{$$self};
119 4         21 delete $dat_out{$$self};
120 4         345 $self->SUPER::DESTROY;
121             }
122              
123             1;
124              
125             __END__