require 'rmail'
require 'cgi'
+## TODO: remove synchronized method protector calls; use a Monitor instead
+## (ruby's reentrant mutex)
+
## fucking imap fucking sucks. what the FUCK kind of committee of dunces
## designed this shit.
##
## restriction. it can change any time you log in. it can change EVERY
## time you log in. of course the imap spec "strongly recommends" that it
## never change, but there's nothing to stop people from just setting it
-## to the current timestamp, and in fact that's exactly what the one imap
+## to the current timestamp, and in fact that's EXACTLY what the one imap
## server i have at my disposal does. thus the so-called uids are
## absolutely useless and imap provides no cross-session way of uniquely
## identifying a message. but thanks for the "strong recommendation",
require 'fileutils'
require 'ferret'
+require 'fastthread'
+
begin
require 'chronic'
$have_chronic = true
@dir = dir
@sources = {}
@sources_dirty = false
+ @source_mutex = Monitor.new
wsa = Ferret::Analysis::WhiteSpaceAnalyzer.new false
sa = Ferret::Analysis::StandardAnalyzer.new [], true
end
def add_source source
- raise "duplicate source!" if @sources.include? source
- @sources_dirty = true
- max = @sources.max_of { |id, s| s.is_a?(DraftLoader) || s.is_a?(SentLoader) ? 0 : id }
- source.id ||= (max || 0) + 1
- ##source.id += 1 while @sources.member? source.id
- @sources[source.id] = source
+ @source_mutex.synchronize do
+ raise "duplicate source!" if @sources.include? source
+ @sources_dirty = true
+ max = @sources.max_of { |id, s| s.is_a?(DraftLoader) || s.is_a?(SentLoader) ? 0 : id }
+ source.id ||= (max || 0) + 1
+ ##source.id += 1 while @sources.member? source.id
+ @sources[source.id] = source
+ end
end
def sources
## favour the inbox by listing non-archived sources first
- @sources.values.sort_by { |s| s.id }.partition { |s| !s.archived? }.flatten
+ @source_mutex.synchronize { @sources.values }.sort_by { |s| s.id }.partition { |s| !s.archived? }.flatten
end
def source_for uri; sources.find { |s| s.is_source_for? uri }; end
## builds a message object from a ferret result
def build_message docid
doc = @index[docid]
- source = @sources[doc[:source_id].to_i]
+ source = @source_mutex.synchronize { @sources[doc[:source_id].to_i] }
#puts "building message #{doc[:message_id]} (#{source}##{doc[:source_info]})"
raise "invalid source #{doc[:source_id]}" unless source
def load_sources fn=Redwood::SOURCE_FN
source_array = (Redwood::load_yaml_obj(fn) || []).map { |o| Recoverable.new o }
- @sources = Hash[*(source_array).map { |s| [s.id, s] }.flatten]
- @sources_dirty = false
+ @source_mutex.synchronize do
+ @sources = Hash[*(source_array).map { |s| [s.id, s] }.flatten]
+ @sources_dirty = false
+ end
end
def has_any_from_source_with_label? source, label
end
def save_sources fn=Redwood::SOURCE_FN
- if @sources_dirty || @sources.any? { |id, s| s.dirty? }
- bakfn = fn + ".bak"
- if File.exists? fn
+ @source_mutex.synchronize do
+ if @sources_dirty || @sources.any? { |id, s| s.dirty? }
+ bakfn = fn + ".bak"
+ if File.exists? fn
+ File.chmod 0600, fn
+ FileUtils.mv fn, bakfn, :force => true unless File.exists?(bakfn) && File.size(fn) == 0
+ end
+ Redwood::save_yaml_obj sources.sort_by { |s| s.id.to_i }, fn, true
File.chmod 0600, fn
- FileUtils.mv fn, bakfn, :force => true unless File.exists?(bakfn) && File.size(fn) == 0
end
- Redwood::save_yaml_obj sources.sort_by { |s| s.id.to_i }, fn, true
- File.chmod 0600, fn
+ @sources_dirty = false
end
- @sources_dirty = false
end
end