#include "../../context.h"
#include "../../ctdl_module.h"
-
// These can be global variables because only one indexer runs at a time.
Array *messages_to_be_indexed = NULL;
long highest_msg_already_indexed = 0;
array_len(tokens_in_this_message)
);
+ if (tokens_in_this_message == NULL) {
+ return;
+ }
+
if (array_len(tokens_in_this_message) > 0) {
begin_critical_section(S_INDEXER);
cdb_begin_transaction();
int i;
static time_t last_progress = 0L;
static int is_running = 0;
+
if (is_running) return; // Concurrency check - only one can run
is_running = 1;
// Don't do this if the site doesn't have it enabled.
if (!CtdlGetConfigInt("c_enable_fulltext")) {
+ is_running = 0;
return;
}
- syslog(LOG_DEBUG, "fulltext: indexing started");
-
// If we've switched wordbreaker modules, burn the index and start over.
begin_critical_section(S_CONTROL);
if (CtdlGetConfigInt("MM_fulltext_wordbreaker") != FT_WORDBREAKER_ID) {
// Silently return if our fulltext index is up to date with new messages.
if ((CtdlGetConfigLong("MMfulltext") >= CtdlGetConfigLong("MMhighest"))) {
+ is_running = 0;
return; // nothing to do!
}
highest_msg_already_indexed = CtdlGetConfigLong("MMfulltext");
highest_msg_to_be_indexed = CtdlGetConfigLong("MMhighest");
+ syslog(LOG_DEBUG, "fulltext: indexing started. msgs %ld--%ld", highest_msg_already_indexed, highest_msg_to_be_indexed);
+
messages_to_be_indexed = array_new(sizeof(long));
// Now go through each room and find messages to index.
// Here it is ... do each message!
long msgnum = 0;
long prev_msgnum = 0;
- for (i=0; i<array_len(messages_to_be_indexed); ++i) {
+ time_t started_indexing_at = time(NULL);
+ int yielded = 0;
+ for (i=0; ((i<array_len(messages_to_be_indexed)) && (yielded == 0)); ++i) {
memcpy(&msgnum, array_get_element_at(messages_to_be_indexed, i), sizeof(long));
if (msgnum != prev_msgnum) { // careful to avoid dupes
ft_index_message(msgnum, 1);
}
-
prev_msgnum = msgnum;
+
+ // If we run too long, yield the thread so the server can do other things. We'll be back.
+ if (time(NULL) - started_indexing_at >= MAXIMUM_INDEXER_RUN_TIME) {
+ yielded = 1;
+ }
}
array_free(messages_to_be_indexed);
-
CtdlSetConfigInt("MM_fulltext_wordbreaker", FT_WORDBREAKER_ID);
+ syslog(LOG_DEBUG, "fulltext: indexer has run for %ld seconds; yielded=%d", time(NULL) - started_indexing_at, yielded);
+
+ // This keeps the indexer from starting up over and over if the highest message in the list was deleted
+ // before we had a chance to index it.
+ if (!yielded) {
+ CtdlSetConfigLong("MMfulltext", highest_msg_to_be_indexed);
+ }
- syslog(LOG_DEBUG, "fulltext: indexing finished");
is_running = 0;
return;
}
// API call to perform searches.
// (This one does the "all of these words" search.)
// Caller is responsible for freeing the message list.
-Array *ft_search(const char *search_string) {
+Array *CtdlFullTextSearch(const char *search_string) {
int i, j, tok;
struct cdbdata cdb_bucket;
long msgnum, smsgnum;
}
extract_token(search_string, argbuf, 0, '|', sizeof search_string);
- matches = ft_search(search_string);
+ matches = CtdlFullTextSearch(search_string);
cprintf("%d %d msgs match all search words:\n", LISTING_FOLLOWS, array_len(matches));
if ((matches != NULL) && (array_len(matches) > 0)) {
if (!threading) {
CtdlRegisterProtoHook(cmd_srch, "SRCH", "Full text search");
CtdlRegisterDeleteHook(ft_delete_remove);
- //CtdlRegisterSearchFuncHook(ft_search, "fulltext");
- CtdlRegisterSessionHook(do_fulltext_indexing, EVT_TIMER, PRIO_CLEANUP + 300);
+ CtdlRegisterSessionHook(do_fulltext_indexing, EVT_HOUSE, PRIO_CLEANUP + 300);
}
// return our module name for the log
return "fulltext";