package KinoSearch::Index::SegInfos; use strict; use warnings; use KinoSearch::Util::ToolSet; use base qw( KinoSearch::Util::Class ); use constant FORMAT => -1; BEGIN { __PACKAGE__->init_instance_vars( # members infos => undef, counter => 0, version => undef, ); __PACKAGE__->ready_get_set(qw( counter )); } use Time::HiRes qw( time ); sub init_instance { my $self = shift; $self->{infos} = {}; $self->{version} ||= int(time * 1000); } # Add a SegInfo to the collection. sub add_info { my ( $self, $info ) = @_; $self->{infos}{"$info->{seg_name}"} = $info; } # Remove the info corresponding to a segment; sub delete_segment { my ( $self, $seg_name ) = @_; confess("no segment named '$seg_name'") unless exists $self->{infos}{$seg_name}; delete $self->{infos}{$seg_name}; } # Return number of segments in invindex. sub size { scalar keys %{ $_[0]->{infos} } } # Retrieve all infos. sub infos { sort { $a->{seg_name} cmp $b->{seg_name} } values %{ $_[0]->{infos} }; } # Decode "segments" file. sub read_infos { my ( $self, $invindex ) = @_; my $instream = $invindex->open_instream('segments'); # support only recent index formats my $format = $instream->lu_read('i'); croak("unsupported format: '$format'") unless $format == FORMAT; # read header @{$self}{ 'version', 'counter' } = $instream->lu_read('Qi'); my $num_segs = $instream->lu_read('i'); # build one SegInfo object for each segment if ($num_segs) { my @file_contents = $instream->lu_read( 'Ti' x $num_segs ); while (@file_contents) { my ( $seg_name, $doc_count ) = splice( @file_contents, 0, 2 ); $self->{infos}{$seg_name} = KinoSearch::Index::SegInfo->new( seg_name => $seg_name, doc_count => $doc_count, invindex => $invindex, ); } } } # Write "segments" file sub write_infos { my ( $self, $invindex ) = @_; my $num_segs = scalar keys %{ $self->{infos} }; my $outstream = $invindex->open_outstream('segments.new'); # prepare header $self->{version}++; my @outstuff = ( FORMAT, $self->{version}, $self->{counter}, $num_segs ); # prepare data push @outstuff, map { ( $self->{infos}{$_}{seg_name}, $self->{infos}{$_}{doc_count} ) } sort keys %{ $self->{infos} }; # write it all out my $template = 'iQii' . ( 'Ti' x $num_segs ); $outstream->lu_write( $template, @outstuff ); $outstream->close; # clobber the old segments file $invindex->rename_file( "segments.new", "segments" ); } package KinoSearch::Index::SegInfo; use strict; use warnings; use KinoSearch::Util::ToolSet; use base qw( KinoSearch::Util::Class ); BEGIN { __PACKAGE__->init_instance_vars( # constructor params / members seg_name => '', doc_count => 0, invindex => undef, ); __PACKAGE__->ready_get(qw( seg_name doc_count invindex )); } 1; __END__ =begin devdocs =head1 NAME KinoSearch::Index::SegInfos - manage segment statistical data =head1 DESCRIPTION SegInfos ties together the segments which make up an invindex. It stores a little information about each, plus some unifying information such as the counter used to name new segments. =head1 COPYRIGHT Copyright 2005-2007 Marvin Humphrey =head1 LICENSE, DISCLAIMER, BUGS, etc. See L version 0.163. =end devdocs =cut