1
inherit Service.Service;
3
Thread.Queue oQueue = Thread.Queue();
4
Thread.Mutex mBuffer = Thread.Mutex();
8
mapping mStripFilter = ([ ]);
11
#include <attributes.h>
12
#include <configure.h>
21
void create(object o) {
23
mime = o->query_attribute(DOC_MIME_TYPE);
24
name = o->get_identifier();
25
werror("Mimetype for %s is %O\n", name, mime);
26
id = o->get_object_id();
27
content_id = o->get_content_id();
31
void notify(mixed args)
33
werror("EVENT_UPLOAD in fulltext.pike [%O]\n" , args);
35
tStripDemon = thread_create(strip_demon);
36
Doc doc = Doc(args[0]);
40
void call_service(object user, mixed args, int|void id)
42
werror("Service called with %O\n", args);
50
werror("Content Strip Service Demon started.\n");
54
Doc oDocument = oQueue->read();
55
werror("Indexing Document !\n");
56
string sMime = oDocument->mime;
59
sStripHandler = mStripFilter[sMime];
63
int iContentID = oDocument->content_id;
64
int iObID = oDocument->id;
65
Stdio.File temp = Stdio.File("buffer.file", "rwct");
66
Sql.Sql handle = Sql.Sql(serverCfg["database"]);
68
handle->big_query("select rec_data from doc_data where "+
69
"doc_id = "+iContentID+
70
" order by rec_order");
71
while (mixed data = res->fetch_row())
74
Stdio.File infile = Stdio.File("buffer.file");
76
if ( strlen(sStripHandler) > 0 ) {
77
Stdio.File outfile = Stdio.File("strip.file","wct");
79
int PCode = Process.create_process(
82
"stdout" : outfile]))->wait();
83
werror("Fulltext - stripped content length is %d\n",
84
Stdio.file_size("strip.file"));
87
werror("Error during content stripping:\n"+
88
master()->describe_backtrace(err));
90
outfile->open("strip.file","r");
91
query = "replace into doc_ft values("+iObID+","+
93
handle->quote(outfile->read())+"\")";
96
string cbuffer = Stdio.read_file("buffer.file");
97
werror("Updating indexof %d: %d bytes...\n",
100
query = "replace into doc_ft values("+iObID+","+
102
handle->quote(cbuffer)+"\")";
104
handle->big_query(query);
107
werror("No Striphandler configured for %O (%O)\n", sMime,
112
mixed search_documents(string pattern)
114
object handle = Sql.Sql(serverCfg["database"]);
115
object result = handle->big_query("select ob_id, match(doc_data) against(%s) from doc_ft where match(doc_data) against(%s)", pattern, pattern);
118
while (row = result->fetch_row())
125
static void create_table(string dbhandle)
127
Sql.Sql handle = Sql.Sql(dbhandle);
128
handle->query("create table if not exists doc_ft (ob_id int, "+
129
"doc_id int, doc_data TEXT, FULLTEXT(doc_data))");
134
* create temporary table ft_id (ob_id int primary key, count int);
135
* insert into ft_id select ob_id, 0 from ob_data where ob_attr='DOC_MIME_TYPE' and ob_data='"text/html"';
136
* replace into ft_id select ob_id, 1 from doc_ft;
137
* delete from ft_id where count = 1;
139
static void check_ft_integrity()
141
Sql.Sql handle = Sql.Sql(serverCfg["database"]);
142
handle->query("create temporary table ft_id "+
143
"(ob_id int primary key, count int)");
144
handle->query("insert into ft_id select distinct "+
145
"ob_id,0 from ob_data where ob_attr='DOC_MIME_TYPE'"+
147
indices(mStripFilter)*"\"' or ob_data='\""+"\"'");
148
handle->query("replace into ft_id select distinct ob_id, 1 from doc_ft");
149
handle->query("delete from ft_id where count =1");
150
array missing = handle->query("select distinct ob_id from ft_id");
151
handle->query("drop table ft_id");
152
foreach (missing, mixed a)
154
object o = connection->find_object((int)a["ob_id"]);
156
oQueue->write(Doc(o));
160
static private void got_kill(int sig)
165
int main(int argc, array argv)
167
init( "fulltext", argv + ({ "--eid="+EVENT_UPLOAD }) );
169
if (catch{mStripFilter = read_config_file(CONFIG_DIR+"/services/fulltext.cfg");})
170
mStripFilter = ([ "text/html" : "html2text" ]);
173
if ( !mStripFilter["text/plain"])
174
mStripFilter["text/plain"] = "";
175
signal(signum("QUIT"), got_kill);
178
create_table(serverCfg["database"]);
182
tStripDemon = thread_create(strip_demon);
183
thread_create(check_ft_integrity);
186
werror("Startup of fulltext service failed.\n"+
187
master()->describe_backtrace(err)+"\n");
191
mapping read_config_file(string fname)
193
Parser.XML.Tree.Node node = Parser.XML.Tree.parse_file(fname);
195
error("Failed to parse config file %s\n", fname);
198
node = node->get_first_element("config");
199
foreach(node->get_elements(), Parser.XML.Tree.Node n)
201
data[n->get_attributes()["mime"]] = n->get_last_child()->get_text();