[KinoSearch] Merging indexes, etc
Marvin Humphrey
marvin at rectangular.com
Mon Oct 30 10:59:00 PST 2006
On Oct 26, 2006, at 6:36 AM, henka at cityweb.co.za wrote:
> Splitting the process into two steps (delete_docs_by_term() and
> add_invindexes()) unfortunately results in the error:
>
> Can't locate object method "_release_locks" via package
> "self" (perhaps
> you forgot to load "self"?) at
> /usr/lib/perl5/site_perl/5.8.7/i486-linux/KinoSearch/InvIndexer.pm
> line
> 273.
Hmm. What the hell is "self" doing there? That really suggests
memory corruption of some kind -- the pointer that used to lead Perl
to the class name has been reused and is now pointing to something
completely different and wrong. That's why I suspected problems with
DESTROY.
I have one more idea, but after that, I'm going to need a failing
test case I can go tear into.
> The logic I used:
>
> my $iv;
> foreach (sub-indexes) {
> $iv= KinoSearch::InvIndexer->new(...);
> $iv->delete_docs_by_term(...);
> $iv->finish(optimize=>0);
> $iv= KinoSearch::InvIndexer->new(...); # same sub-index as previous
> $iv->add_invindexes(...);
> $iv->finish(optimize=>0);
> }
Try undef-ing the InvIndexer before assigning another one on top of
it. Take a look at the create_test_invindex() function in <http://
www.rectangular.com/svn/kinosearch/trunk/buildlib/
KinoSearchTestInvIndex.pm> for a template.
I'm not sure that you're seeing the same problem I've been seeing,
but code like in your example, where a new InvIndexer instance is
created in the same scalar variable, has caused me problems in the
past. The symptoms were slightly different: it was lock contention
rather than a failed call to _release_locks.
The sequence "$invindexer = new_invindexer(); $invindexer =
new_invindexer();" is problematic, because the second assignment
statement triggers this order of operations:
1) Create new InvIndexer, put it in a mortal SV on
the Perl stack.
2) Assign the new InvIndexer object to the scalar
which previously held another invindexer.
3) The old scalar's reference count is decremented
and the old InvIndexer's DESTROY method gets called.
In step 1, the new InvIndexer requests a lock. But the old
InvIndexer doesn't release its lock until step 3.
I'd like to solve this problem, but I'm not sure how to do it in the
general case. I've thought of doing something like this, using
closures:
# in new()
$self->{release_locks} = sub { $self->do_release_locks };
# in finish()
$self->{release_locks}->();
undef $self->{release_locks};
# in DESTROY
$self->{release_locks}->() if defined $self->{release_locks};
But I think that would still fail if finish() never gets called.
Marvin Humphrey
Rectangular Research
http://www.rectangular.com/
More information about the kinosearch
mailing list