#include "KinoSearch/Util/ToolSet.h"
#define KINO_WANT_SEGLEXCACHE_VTABLE
#include "KinoSearch/Index/SegLexCache.r"
#include "KinoSearch/Schema.r"
#include "KinoSearch/FieldSpec.r"
#include "KinoSearch/Index/IndexFileNames.h"
#include "KinoSearch/Index/SegInfo.r"
#include "KinoSearch/Index/SegLexicon.r"
#include "KinoSearch/Index/Term.r"
#include "KinoSearch/Index/TermInfo.r"
#include "KinoSearch/Store/Folder.r"
/* Iterate through a SegLexicon reading the .lexx file, caching term texts
* and tinfos.
*/
static void
fill_cache(SegLexCache* self);
SegLexCache*
SegLexCache_new(Schema *schema, Folder *folder, SegInfo *seg_info,
const struct kino_ByteBuf *field)
{
SegLexCache *self;
FieldSpec *fspec = Schema_Fetch_FSpec(schema, field);
ByteBuf *filename;
const ByteBuf empty = BYTEBUF_BLANK;
i32_t field_num = SegInfo_Field_Num(seg_info, field);
/* if the field isn't indexed, bail out */
if ( !fspec || !fspec->indexed )
return NULL;
/* bail out if there are no terms for this field in this segment */
field_num = SegInfo_Field_Num(seg_info, field);
filename = BB_new(40);
BB_Cat_BB(filename, seg_info->seg_name);
BB_Cat_Str(filename, ".lexx", 5);
BB_Cat_I64(filename, (i64_t)field_num);
if ( !Folder_File_Exists(folder, filename) ) {
REFCOUNT_DEC(filename);
return NULL;
}
REFCOUNT_DEC(filename);
/* CREATE */
self = MALLOCATE(1, SegLexCache);
self->_ = &SEGLEXCACHE;
self->refcount = 1;
/* init */
self->term_texts = NULL;
self->tinfos = NULL;
self->locked = false;
self->tick = 0;
/* derive */
self->term = Term_new(field, &empty);
self->field_num = field_num;
self->index_interval = schema->index_interval;
/* assign */
self->schema = REFCOUNT_INC(schema);
self->folder = REFCOUNT_INC(folder);
self->seg_info = REFCOUNT_INC(seg_info);
self->field = BB_CLONE(field);
/* allocate and fill caches */
fill_cache(self);
return self;
}
static void
fill_cache(SegLexCache* self)
{
TermInfo **tinfos;
ByteBuf **term_texts;
SegLexicon *seed_lexicon = SegLex_new(self->schema, self->folder,
self->seg_info, self->field, NULL, true);
/* allocate space */
self->size = seed_lexicon->size;
self->term_texts = MALLOCATE((u32_t)self->size, ByteBuf*);
self->tinfos = MALLOCATE((u32_t)self->size, TermInfo*);
tinfos = self->tinfos;
term_texts = self->term_texts;
/* copy tinfo and term_texts into caches */
while (SegLex_Next(seed_lexicon)) {
Term *const term = SegLex_Get_Term(seed_lexicon);
TermInfo *const tinfo = SegLex_Get_Term_Info(seed_lexicon);
*tinfos++ = (TermInfo*)Obj_Clone(tinfo);
*term_texts++ = BB_CLONE(term->text);
}
/* clean up */
REFCOUNT_DEC(seed_lexicon);
}
void
SegLexCache_destroy(SegLexCache *self)
{
/* free caches */
i32_t i;
ByteBuf **term_texts = self->term_texts;
TermInfo **tinfos = self->tinfos;
for (i = 0; i < self->size; i++) {
REFCOUNT_DEC(*term_texts);
REFCOUNT_DEC(*tinfos);
term_texts++, tinfos++;
}
free(self->term_texts);
free(self->tinfos);
/* kill off members */
REFCOUNT_DEC(self->schema);
REFCOUNT_DEC(self->folder);
REFCOUNT_DEC(self->seg_info);
REFCOUNT_DEC(self->term);
REFCOUNT_DEC(self->field);
/* last, the object itself */
free(self);
}
void
SegLexCache_lock(SegLexCache *self)
{
if (self->locked)
CONFESS("Lexicon is already locked");
self->locked = true;
}
void
SegLexCache_unlock(SegLexCache *self)
{
if ( !self->locked )
CONFESS("Lexicon isn't locked");
self->locked = false;
}
kino_TermInfo*
SegLexCache_get_term_info(SegLexCache *self)
{
return self->tinfos[ self->tick ];
}
/* Copyright 2006-2007 Marvin Humphrey
*
* This program is free software; you can redistribute it and/or modify
* under the same terms as Perl itself.
*/