Beispiel #1
0
Datum
dispell_init(PG_FUNCTION_ARGS)
{
	List	   *dictoptions = (List *) PG_GETARG_POINTER(0);
	DictISpell *d;
	bool		affloaded = false,
				dictloaded = false,
				stoploaded = false;
	ListCell   *l;

	d = (DictISpell *) palloc0(sizeof(DictISpell));

	NIStartBuild(&(d->obj));

	foreach(l, dictoptions)
	{
		DefElem    *defel = (DefElem *) lfirst(l);

		if (pg_strcasecmp(defel->defname, "DictFile") == 0)
		{
			if (dictloaded)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						 errmsg("multiple DictFile parameters")));
			NIImportDictionary(&(d->obj),
							 get_tsearch_config_filename(defGetString(defel),
														 "dict"));
			dictloaded = true;
		}
		else if (pg_strcasecmp(defel->defname, "AffFile") == 0)
		{
			if (affloaded)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						 errmsg("multiple AffFile parameters")));
			NIImportAffixes(&(d->obj),
							get_tsearch_config_filename(defGetString(defel),
														"affix"));
			affloaded = true;
		}
		else if (pg_strcasecmp(defel->defname, "StopWords") == 0)
		{
			if (stoploaded)
				ereport(ERROR,
						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
						 errmsg("multiple StopWords parameters")));
			readstoplist(defGetString(defel), &(d->stoplist), lowerstr);
			stoploaded = true;
		}
		else
		{
			ereport(ERROR,
					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
					 errmsg("unrecognized Ispell parameter: \"%s\"",
							defel->defname)));
		}
	}
Datum
spell_init(PG_FUNCTION_ARGS)
{
	DictISpell *d;
	Map		   *cfg,
			   *pcfg;
	text	   *in;
	bool		affloaded = false,
				dictloaded = false,
				stoploaded = false;

	if (PG_ARGISNULL(0) || PG_GETARG_POINTER(0) == NULL)
		ereport(ERROR,
				(errcode(ERRCODE_CONFIG_FILE_ERROR),
				 errmsg("ISpell confguration error")));

	d = (DictISpell *) malloc(sizeof(DictISpell));
	if (!d)
		ereport(ERROR,
				(errcode(ERRCODE_OUT_OF_MEMORY),
				 errmsg("out of memory")));
	memset(d, 0, sizeof(DictISpell));
	d->stoplist.wordop = lowerstr;

	in = PG_GETARG_TEXT_P(0);
	parse_cfgdict(in, &cfg);
	PG_FREE_IF_COPY(in, 0);
	pcfg = cfg;
	while (pcfg->key)
	{
		if (pg_strcasecmp("DictFile", pcfg->key) == 0)
		{
			if (dictloaded)
			{
				freeDictISpell(d);
				ereport(ERROR,
					  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
					   errmsg("dictionary already loaded")));
			}
			if (NIImportDictionary(&(d->obj), pcfg->value))
			{
				freeDictISpell(d);
				ereport(ERROR,
						(errcode(ERRCODE_CONFIG_FILE_ERROR),
						 errmsg("could not load dictionary file \"%s\"",
								pcfg->value)));
			}
			dictloaded = true;
		}
		else if (pg_strcasecmp("AffFile", pcfg->key) == 0)
		{
			if (affloaded)
			{
				freeDictISpell(d);
				ereport(ERROR,
					  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
					   errmsg("affixes already loaded")));
			}
			if (NIImportAffixes(&(d->obj), pcfg->value))
			{
				freeDictISpell(d);
				ereport(ERROR,
						(errcode(ERRCODE_CONFIG_FILE_ERROR),
						 errmsg("could not load affix file \"%s\"",
								pcfg->value)));
			}
			affloaded = true;
		}
		else if (pg_strcasecmp("StopFile", pcfg->key) == 0)
		{
			text	   *tmp = char2text(pcfg->value);

			if (stoploaded)
			{
				freeDictISpell(d);
				ereport(ERROR,
					  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
					   errmsg("stop words already loaded")));
			}
			readstoplist(tmp, &(d->stoplist));
			sortstoplist(&(d->stoplist));
			pfree(tmp);
			stoploaded = true;
		}
		else
		{
			freeDictISpell(d);
			ereport(ERROR,
					(errcode(ERRCODE_SYNTAX_ERROR),
					 errmsg("unrecognized option: %s => %s",
							pcfg->key, pcfg->value)));
		}
		pfree(pcfg->key);
		pfree(pcfg->value);
		pcfg++;
	}
	pfree(cfg);

	if (affloaded && dictloaded)
	{
		NISortDictionary(&(d->obj));
		NISortAffixes(&(d->obj));
	}
	else if (!affloaded)
	{
		freeDictISpell(d);
		ereport(ERROR,
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
				 errmsg("no affixes")));
	}
	else
	{
		freeDictISpell(d);
		ereport(ERROR,
				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
				 errmsg("no dictionary")));
	}

	PG_RETURN_POINTER(d);
}
Beispiel #3
0
/*
 * Initializes the dictionary for use in backends - checks whether such dictionary 
 * and list of stopwords is already used, and if not then parses it and loads it into
 * the shared segment.
 * 
 * This is called through dispell_init() which is responsible for proper locking
 * of the shared memory (using SegmentInfo->lock).
 */
static
void init_shared_dict(DictInfo * info, char * dictFile, char * affFile, char * stopFile) {

    int size;

    SharedIspellDict * shdict = NULL;
    SharedStopList * shstop   = NULL;

    IspellDict * dict;
    StopList    stoplist;
    
    /* DICTIONARY + AFFIXES */
    
    /* TODO This should probably check that the filenames are not NULL, and maybe that
     * it exists. Or maybe that's handled by the NIImport* functions. */

    /* lookup if the dictionary (words and affixes) is already loaded in the shared segment */
    shdict = get_shared_dict(dictFile, affFile);

    /* load the dictionary / affixes if not yet defined */
    if (shdict == NULL) {

        dict = (IspellDict *)palloc0(sizeof(IspellDict));

        NIStartBuild(dict);

        NIImportDictionary(dict,
                           get_tsearch_config_filename(dictFile, "dict"));

        NIImportAffixes(dict,
                        get_tsearch_config_filename(affFile, "affix"));

        NISortDictionary(dict);
        NISortAffixes(dict);

        NIFinishBuild(dict);

        /* check available space in shared segment */
        size = sizeIspellDict(dict, dictFile, affFile);
        if (size > segment_info->available)
            elog(ERROR, "shared dictionary %s.dict / %s.affix needs %d B, only %ld B available",
                 dictFile, affFile, size, segment_info->available);

        /* fine, there's enough space - copy the dictionary */
        shdict = copyIspellDict(dict, dictFile, affFile, size, dict->nspell);

        elog(INFO, "shared dictionary %s.dict / %s.affix loaded, used %d B, %ld B remaining",
             dictFile, affFile, size, segment_info->available);

        /* add the new dictionary to the linked list (of SharedIspellDict structures) */
        shdict->next = segment_info->dict;
        segment_info->dict = shdict;

    }
    
    /* STOP WORDS */

    /* lookup if the stop words are already loaded in the shared segment, but only if there
     * actually is a list */
    if (stopFile != NULL) {

        shstop = get_shared_stop_list(stopFile);

        /* load the stopwords if not yet defined */
        if (shstop == NULL) {

            readstoplist(stopFile, &stoplist, lowerstr);

            size = sizeStopList(&stoplist, stopFile);
            if (size > segment_info->available) {
                elog(ERROR, "shared stoplist %s.stop needs %d B, only %ld B available",
                     stopFile, size, segment_info->available);
            }

            /* fine, there's enough space - copy the stoplist */
            shstop = copyStopList(&stoplist, stopFile, size);

            elog(INFO, "shared stoplist %s.stop loaded, used %d B, %ld B remaining",
                 affFile, size, segment_info->available);

            /* add the new stopword list to the linked list (of SharedStopList structures) */
            shstop->next = segment_info->stop;
            segment_info->stop = shstop;

        }
    }

    /* Now, fill the DictInfo structure for the backend (references to dictionary,
     * stopwords and the filenames). */

    info->dict = shdict;
    info->stop = shstop;
    info->lookup = GetCurrentTimestamp();

    memcpy(info->dictFile, dictFile, strlen(dictFile) + 1);
    memcpy(info->affixFile, dictFile, strlen(affFile)+ 1);
    memcpy(info->stopFile, dictFile, strlen(stopFile) + 1);

}