def each_message_in_thread_for m, opts={}
messages = {}
searched = {}
num_queries = 0
pending = [m.id]
if $config[:thread_by_subject]
date_min = m.date - (SAME_SUBJECT_DATE_LIMIT * 12 * 3600)
date_max = m.date + (SAME_SUBJECT_DATE_LIMIT * 12 * 3600)
q = Ferret::Search::BooleanQuery.new true
sq = Ferret::Search::PhraseQuery.new(:subject)
wrap_subj(Message.normalize_subj(m.subj)).split.each do |t|
sq.add_term t
end
q.add_query sq, :must
q.add_query Ferret::Search::RangeQuery.new(:date, :>= => date_min.to_indexable_s, :<= => date_max.to_indexable_s), :must
q = build_ferret_query :qobj => q
p1 = @index_mutex.synchronize { @index.search(q).hits.map { |hit| @index[hit.doc][:message_id] } }
debug "found #{p1.size} results for subject query #{q}"
p2 = @index_mutex.synchronize { @index.search(q.to_s, :limit => :all).hits.map { |hit| @index[hit.doc][:message_id] } }
debug "found #{p2.size} results in string form"
pending = (pending + p1 + p2).uniq
end
until pending.empty? || (opts[:limit] && messages.size >= opts[:limit])
q = Ferret::Search::BooleanQuery.new true
lim = [MAX_CLAUSES / 2, pending.length].min
pending[0 ... lim].each do |id|
searched[id] = true
q.add_query Ferret::Search::TermQuery.new(:message_id, id), :should
q.add_query Ferret::Search::TermQuery.new(:refs, id), :should
end
pending = pending[lim .. -1]
q = build_ferret_query :qobj => q
num_queries += 1
killed = false
@index_mutex.synchronize do
@index.search_each(q, :limit => :all) do |docid, score|
break if opts[:limit] && messages.size >= opts[:limit]
if @index[docid][:label].split(/\s+/).include?("killed") && opts[:skip_killed]
killed = true
break
end
mid = @index[docid][:message_id]
unless messages.member?(mid)
messages[mid] ||= lambda { build_message docid }
refs = @index[docid][:refs].split
pending += refs.select { |id| !searched[id] }
end
end
end
end
if killed
false
else
messages.each { |mid, builder| yield mid, builder }
true
end
end