1 ## Index interface, subclassed by Ferret indexer.
9 Redwood::log "optional 'chronic' library not found (run 'gem install chronic' to install)"
16 include InteractiveLock
18 class LockError < StandardError
23 def method_missing m; @h[m.to_s] end
28 def initialize dir=BASE_DIR
30 @lock = Lockfile.new lockfile, :retries => 0, :max_age => nil
31 self.class.i_am_the_instance self
34 def lockfile; File.join @dir, "lock" end
37 Redwood::log "locking #{lockfile}..."
40 rescue Lockfile::MaxTriesLockError
41 raise LockError, @lock.lockinfo_on_disk
45 def start_lock_update_thread
46 @lock_update_thread = Redwood::reporting_thread("lock update") do
54 def stop_lock_update_thread
55 @lock_update_thread.kill if @lock_update_thread
56 @lock_update_thread = nil
60 if @lock && @lock.locked?
61 Redwood::log "unlocking #{lockfile}..."
67 SourceManager.load_sources
72 Redwood::log "saving index and sources..."
73 FileUtils.mkdir_p @dir unless File.exists? @dir
74 SourceManager.save_sources
82 ## Syncs the message to the index, replacing any previous version. adding
83 ## either way. Index state will be determined by the message's #labels
85 def sync_message m, opts={}
97 def contains? m; contains_id? m.id end
103 def empty?; size == 0 end
105 ## Yields a message-id and message-building lambda for each
106 ## message that matches the given query, in descending date order.
107 ## You should probably not call this on a block that doesn't break
108 ## rather quickly because the results can be very large.
109 def each_id_by_date query={}
113 ## Return the number of matches for query in the index
114 def num_results_for query={}
118 ## yield all messages in the thread containing 'm' by repeatedly
119 ## querying the index. yields pairs of message ids and
120 ## message-building lambdas, so that building an unwanted message
121 ## can be skipped in the block if desired.
123 ## only two options, :limit and :skip_killed. if :skip_killed is
124 ## true, stops loading any thread if a message with a :killed flag
126 def each_message_in_thread_for m, opts={}
130 ## Load message with the given message-id from the index
135 ## Delete message with the given message-id from the index
140 ## Given an array of email addresses, return an array of Person objects that
141 ## have sent mail to or received mail from any of the given addresses.
142 def load_contacts email_addresses, h={}
146 ## Yield each message-id matching query
151 ## Yield each message matching query
152 def each_message query={}, &b
153 each_id query do |id|
154 yield build_message(id)
158 ## Implementation-specific optimization step
163 ## Return the id source of the source the message with the given message-id
169 class ParseError < StandardError; end
171 ## parse a query string from the user. returns a query object
172 ## that can be passed to any index method with a 'query'
175 ## raises a ParseError if something went wrong.
181 index_name = ENV['SUP_INDEX'] || $config[:index] || DEFAULT_INDEX
183 when "xapian"; require "sup/xapian_index"
184 when "ferret"; require "sup/ferret_index"
185 else fail "unknown index type #{index_name.inspect}"
187 Index = Redwood.const_get "#{index_name.capitalize}Index"
188 Redwood::log "using index #{Index.name}"