File Coverage

blib/lib/KinoSearch1/Index/SegInfos.pm
Criterion Covered Total %
statement 72 74 97.3
branch 4 8 50.0
condition 1 3 33.3
subroutine 18 19 94.7
pod 1 7 14.2
total 96 111 86.4


line stmt bran cond sub pod time code
1             package KinoSearch1::Index::SegInfos;
2 34     34   33683 use strict;
  34         152  
  34         1232  
3 34     34   270 use warnings;
  34         70  
  34         943  
4 34     34   894 use KinoSearch1::Util::ToolSet;
  34         70  
  34         5121  
5 34     34   214 use base qw( KinoSearch1::Util::Class );
  34         81  
  34         3765  
6              
7 34     34   204 use constant FORMAT => -1;
  34         95  
  34         3147  
8              
9             BEGIN {
10 34     34   350 __PACKAGE__->init_instance_vars(
11             # members
12             infos => undef,
13             counter => 0,
14             version => undef,
15             );
16 34         305 __PACKAGE__->ready_get_set(qw( counter ));
17             }
18              
19 34     34   40273 use Time::HiRes qw( time );
  34         86386  
  34         218  
20              
21             sub init_instance {
22 129     129 1 271 my $self = shift;
23 129         420 $self->{infos} = {};
24 129   33     1417 $self->{version} ||= int( time * 1000 );
25             }
26              
27             # Add a SegInfo to the collection.
28             sub add_info {
29 61     61 0 141 my ( $self, $info ) = @_;
30 61         454 $self->{infos}{"$info->{seg_name}"} = $info;
31             }
32              
33             # Remove the info corresponding to a segment;
34             sub delete_segment {
35 14     14 0 34 my ( $self, $seg_name ) = @_;
36 14 50       56 confess("no segment named '$seg_name'")
37             unless exists $self->{infos}{$seg_name};
38 14         99 delete $self->{infos}{$seg_name};
39             }
40              
41             # Return number of segments in invindex.
42 0     0 0 0 sub size { scalar keys %{ $_[0]->{infos} } }
  0         0  
43              
44             # Retrieve all infos.
45             sub infos {
46 65     65 0 133 sort { $a->{seg_name} cmp $b->{seg_name} } values %{ $_[0]->{infos} };
  41         130  
  65         442  
47             }
48              
49             # Decode "segments" file.
50             sub read_infos {
51 83     83 0 170 my ( $self, $invindex ) = @_;
52 83         309 my $instream = $invindex->open_instream('segments');
53              
54             # support only recent index formats
55 83         1615 my $format = $instream->lu_read('i');
56 83 50       311 croak("unsupported format: '$format'")
57             unless $format == FORMAT;
58              
59             # read header
60 83         391 @{$self}{ 'version', 'counter' } = $instream->lu_read('Qi');
  83         261  
61 83         379 my $num_segs = $instream->lu_read('i');
62              
63             # build one SegInfo object for each segment
64 83 50       285 if ($num_segs) {
65 83         738 my @file_contents = $instream->lu_read( 'Ti' x $num_segs );
66 83         296 while (@file_contents) {
67 132         359 my ( $seg_name, $doc_count ) = splice( @file_contents, 0, 2 );
68 132         801 $self->{infos}{$seg_name} = KinoSearch1::Index::SegInfo->new(
69             seg_name => $seg_name,
70             doc_count => $doc_count,
71             invindex => $invindex,
72             );
73             }
74             }
75             }
76              
77             # Write "segments" file
78             sub write_infos {
79 107     107 0 251 my ( $self, $invindex ) = @_;
80 107         175 my $num_segs = scalar keys %{ $self->{infos} };
  107         347  
81 107         338 my $tempname = 'segments.new';
82 107 50       378 $invindex->delete_file($tempname) if $invindex->file_exists($tempname);
83 107         431 my $outstream = $invindex->open_outstream($tempname);
84              
85             # prepare header
86 107         286 $self->{version}++;
87 107         425 my @outstuff = ( FORMAT, $self->{version}, $self->{counter}, $num_segs );
88              
89             # prepare data
90 85         567 push @outstuff, map {
91 107         460 ( $self->{infos}{$_}{seg_name}, $self->{infos}{$_}{doc_count} )
92             }
93 107         213 sort keys %{ $self->{infos} };
94              
95             # write it all out
96 107         702 my $template = 'iQii' . ( 'Ti' x $num_segs );
97 107         968 $outstream->lu_write( $template, @outstuff );
98 107         365 $outstream->close;
99              
100             # clobber the old segments file
101 107         480 $invindex->rename_file( $tempname, "segments" );
102             }
103              
104             package KinoSearch1::Index::SegInfo;
105 34     34   41778 use strict;
  34         95  
  34         1671  
106 34     34   699 use warnings;
  34         72  
  34         1383  
107 34     34   221 use KinoSearch1::Util::ToolSet;
  34         76  
  34         6511  
108 34     34   224 use base qw( KinoSearch1::Util::Class );
  34         91  
  34         4641  
109              
110             BEGIN {
111 34     34   438 __PACKAGE__->init_instance_vars(
112             # constructor params / members
113             seg_name => '',
114             doc_count => 0,
115             invindex => undef,
116             );
117 34         824 __PACKAGE__->ready_get(qw( seg_name doc_count invindex ));
118             }
119              
120             1;
121              
122             __END__