#define DETECT_STR_MAX_LEN 200
+struct fts_textcat {
+ int refcount;
+ void *handle;
+ char *config_path, *data_dir, *failed;
+};
+
struct fts_language_list {
pool_t pool;
ARRAY_TYPE(fts_language) languages;
+ struct fts_textcat *textcat;
const char *textcat_config;
const char *textcat_datadir;
- void *textcat_handle;
- const char *textcat_failed;
};
pool_t fts_languages_pool;
ARRAY_TYPE(fts_language) fts_languages;
+#ifdef HAVE_FTS_EXTTEXTCAT
+static struct fts_textcat *fts_textcat_cache = NULL;
+#endif
/* ISO 639-1 alpha 2 codes for languages */
const struct fts_language fts_languages_builtin [] = {
"data"
};
+#ifdef HAVE_FTS_EXTTEXTCAT
+static void fts_textcat_unref(struct fts_textcat *textcat)
+{
+ i_assert(textcat->refcount > 0);
+ if (--textcat->refcount > 0)
+ return;
+
+ if (textcat == fts_textcat_cache)
+ fts_textcat_cache = NULL;
+
+ i_free(textcat->config_path);
+ i_free(textcat->data_dir);
+ i_free(textcat->failed);
+ if (textcat->handle != NULL)
+ textcat_Done(textcat->handle);
+ i_free(textcat);
+}
+#endif
+
void fts_languages_init(void)
{
unsigned int i;
void fts_languages_deinit(void)
{
+#ifdef HAVE_FTS_EXTTEXTCAT
+ if (fts_textcat_cache != NULL)
+ fts_textcat_unref(fts_textcat_cache);
+#endif
pool_unref(&fts_languages_pool);
}
*list = NULL;
#ifdef HAVE_FTS_EXTTEXTCAT
- if (lp->textcat_handle != NULL)
- textcat_Done(lp->textcat_handle);
+ if (lp->textcat != NULL)
+ fts_textcat_unref(lp->textcat);
#endif
pool_unref(&lp->pool);
}
const char *config_path;
const char *data_dir;
- if (list->textcat_handle != NULL)
+ if (list->textcat != NULL) {
+ if (list->textcat->failed != NULL) {
+ *error_r = list->textcat->failed;
+ return -1;
+ }
+ i_assert(list->textcat->handle != NULL);
return 0;
-
- if (list->textcat_failed != NULL) {
- *error_r = list->textcat_failed;
- return -1;
}
-
+
config_path = list->textcat_config != NULL ? list->textcat_config :
TEXTCAT_DATADIR"/fpdb.conf";
data_dir = list->textcat_datadir != NULL ? list->textcat_datadir :
TEXTCAT_DATADIR"/";
- list->textcat_handle = special_textcat_Init(config_path, data_dir);
- if (list->textcat_handle == NULL) {
- *error_r = list->textcat_failed = p_strdup_printf(list->pool,
+ if (fts_textcat_cache != NULL) {
+ if (strcmp(fts_textcat_cache->config_path, config_path) == 0 &&
+ strcmp(fts_textcat_cache->data_dir, data_dir) == 0) {
+ list->textcat = fts_textcat_cache;
+ list->textcat->refcount++;
+ return 0;
+ }
+ fts_textcat_unref(fts_textcat_cache);
+ }
+
+ fts_textcat_cache = list->textcat = i_new(struct fts_textcat, 1);
+ fts_textcat_cache->refcount = 2;
+ fts_textcat_cache->config_path = i_strdup(config_path);
+ fts_textcat_cache->data_dir = i_strdup(data_dir);
+ fts_textcat_cache->handle = special_textcat_Init(config_path, data_dir);
+ if (fts_textcat_cache->handle == NULL) {
+ fts_textcat_cache->failed = i_strdup_printf(
"special_textcat_Init(%s, %s) failed",
config_path, data_dir);
+ *error_r = fts_textcat_cache->failed;
return -1;
}
/* The textcat minimum document size could be set here. It
if (fts_language_textcat_init(list, error_r) < 0)
return FTS_LANGUAGE_RESULT_ERROR;
- candp = textcat_GetClassifyFullOutput(list->textcat_handle);
+ candp = textcat_GetClassifyFullOutput(list->textcat->handle);
if (candp == NULL)
i_fatal_status(FATAL_OUTOFMEM, "textcat_GetCLassifyFullOutput failed: malloc() returned NULL");
- cnt = textcat_ClassifyFull(list->textcat_handle, (const void *)text,
+ cnt = textcat_ClassifyFull(list->textcat->handle, (const void *)text,
I_MIN(size, DETECT_STR_MAX_LEN), candp);
if (cnt > 0) {
T_BEGIN {
match = fts_language_match_lists(list, candp, cnt, lang_r);
} T_END;
- textcat_ReleaseClassifyFullOutput(list->textcat_handle, candp);
+ textcat_ReleaseClassifyFullOutput(list->textcat->handle, candp);
if (match)
return FTS_LANGUAGE_RESULT_OK;
else
return FTS_LANGUAGE_RESULT_UNKNOWN;
} else {
- textcat_ReleaseClassifyFullOutput(list->textcat_handle, candp);
+ textcat_ReleaseClassifyFullOutput(list->textcat->handle, candp);
switch (cnt) {
case TEXTCAT_RESULT_SHORT:
i_assert(size < DETECT_STR_MAX_LEN);