]> git.cworth.org Git - sup/blob - lib/sup/index.rb
refactor index locking interaction and replace suicidemanager
[sup] / lib / sup / index.rb
1 ## Index interface, subclassed by Ferret indexer.
2
3 require 'fileutils'
4
5 begin
6   require 'chronic'
7   $have_chronic = true
8 rescue LoadError => e
9   Redwood::log "optional 'chronic' library not found (run 'gem install chronic' to install)"
10   $have_chronic = false
11 end
12
13 module Redwood
14
15 class BaseIndex
16   include InteractiveLock
17
18   class LockError < StandardError
19     def initialize h
20       @h = h
21     end
22
23     def method_missing m; @h[m.to_s] end
24   end
25
26   include Singleton
27
28   def initialize dir=BASE_DIR
29     @dir = dir
30     @lock = Lockfile.new lockfile, :retries => 0, :max_age => nil
31     self.class.i_am_the_instance self
32   end
33
34   def lockfile; File.join @dir, "lock" end
35
36   def lock
37     Redwood::log "locking #{lockfile}..."
38     begin
39       @lock.lock
40     rescue Lockfile::MaxTriesLockError
41       raise LockError, @lock.lockinfo_on_disk
42     end
43   end
44
45   def start_lock_update_thread
46     @lock_update_thread = Redwood::reporting_thread("lock update") do
47       while true
48         sleep 30
49         @lock.touch_yourself
50       end
51     end
52   end
53
54   def stop_lock_update_thread
55     @lock_update_thread.kill if @lock_update_thread
56     @lock_update_thread = nil
57   end
58
59   def unlock
60     if @lock && @lock.locked?
61       Redwood::log "unlocking #{lockfile}..."
62       @lock.unlock
63     end
64   end
65
66   def load
67     SourceManager.load_sources
68     load_index
69   end
70
71   def save
72     Redwood::log "saving index and sources..."
73     FileUtils.mkdir_p @dir unless File.exists? @dir
74     SourceManager.save_sources
75     save_index
76   end
77
78   def load_index
79     unimplemented
80   end
81
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
84   ## accessor.
85   def sync_message m, opts={}
86     unimplemented
87   end
88
89   def save_index fn
90     unimplemented
91   end
92
93   def contains_id? id
94     unimplemented
95   end
96
97   def contains? m; contains_id? m.id end
98
99   def size
100     unimplemented
101   end
102
103   def empty?; size == 0 end
104
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={}
110     unimplemented
111   end
112
113   ## Return the number of matches for query in the index
114   def num_results_for query={}
115     unimplemented
116   end
117
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.
122   ##
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
125   ## is found.
126   def each_message_in_thread_for m, opts={}
127     unimplemented
128   end
129
130   ## Load message with the given message-id from the index
131   def build_message id
132     unimplemented
133   end
134
135   ## Delete message with the given message-id from the index
136   def delete id
137     unimplemented
138   end
139
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={}
143     unimplemented
144   end
145
146   ## Yield each message-id matching query
147   def each_id query={}
148     unimplemented
149   end
150
151   ## Yield each message matching query
152   def each_message query={}, &b
153     each_id query do |id|
154       yield build_message(id)
155     end
156   end
157
158   ## Implementation-specific optimization step
159   def optimize
160     unimplemented
161   end
162
163   ## Return the id source of the source the message with the given message-id
164   ## was synced from
165   def source_for_id id
166     unimplemented
167   end
168
169   class ParseError < StandardError; end
170
171   ## parse a query string from the user. returns a query object
172   ## that can be passed to any index method with a 'query'
173   ## argument.
174   ##
175   ## raises a ParseError if something went wrong.
176   def parse_query s
177     unimplemented
178   end
179 end
180
181 index_name = ENV['SUP_INDEX'] || $config[:index] || DEFAULT_INDEX
182 case index_name
183   when "xapian"; require "sup/xapian_index"
184   when "ferret"; require "sup/ferret_index"
185   else fail "unknown index type #{index_name.inspect}"
186 end
187 Index = Redwood.const_get "#{index_name.capitalize}Index"
188 Redwood::log "using index #{Index.name}"
189
190 end