commit 2086cffc0a47bd3e115454c8fc0310500e247383
parent c3e15c24b0476d608af8be9ff88e9329d6abad7e
Author: Rich Lane <rlane@club.cc.cmu.edu>
Date: Wed, 19 Jan 2011 20:05:19 -0800
Merge branch 'master' into next
Diffstat:
3 files changed, 114 insertions(+), 0 deletions(-)
diff --git a/bin/sup-import-dump b/bin/sup-import-dump
@@ -0,0 +1,99 @@
+#!/usr/bin/env ruby
+
+require 'uri'
+require 'rubygems'
+require 'trollop'
+require "sup"; Redwood::check_library_version_against "git"
+
+PROGRESS_UPDATE_INTERVAL = 15 # seconds
+
+class AbortExecution < SystemExit
+end
+
+opts = Trollop::options do
+ version "sup-import-dump (sup #{Redwood::VERSION})"
+ banner <<EOS
+Imports message state previously exported by sup-dump into the index.
+sup-import-dump operates on the index only, so the messages must have already
+been added using sup-sync. If you need to recreate the index, see sup-sync
+--restore <filename> instead.
+
+Messages not mentioned in the dump file will not be modified.
+
+Usage:
+ sup-import-dump [options] <dump file>
+
+Options:
+EOS
+ opt :verbose, "Print message ids as they're processed."
+ opt :ignore_missing, "Silently skip over messages that are not in the index."
+ opt :warn_missing, "Warn about messages that are not in the index, but continue."
+ opt :abort_missing, "Abort on encountering messages that are not in the index. (default)"
+ opt :atomic, "Use transaction to apply all changes atomically."
+ opt :dry_run, "Don't actually modify the index. Probably only useful with --verbose.", :short => "-n"
+ opt :version, "Show version information", :short => :none
+
+ conflicts :ignore_missing, :warn_missing, :abort_missing
+end
+Trollop::die "No dump file given" if ARGV.empty?
+Trollop::die "Extra arguments given" if ARGV.length > 1
+dump_name = ARGV.shift
+missing_action = [:ignore_missing, :warn_missing, :abort_missing].find { |x| opts[x] } || :abort_missing
+
+Redwood::start
+index = Redwood::Index.init
+
+index.lock_interactively or exit
+begin
+ num_read = 0
+ num_changed = 0
+ index.load
+ index.begin_transaction if opts[:atomic]
+
+ IO.foreach dump_name do |l|
+ l =~ /^(\S+) \((.*?)\)$/ or raise "Can't read dump line: #{l.inspect}"
+ mid, labels = $1, $2
+ num_read += 1
+
+ unless index.contains_id? mid
+ if missing_action == :abort_missing
+ $stderr.puts "Message #{mid} not found in index, aborting."
+ raise AbortExecution, 10
+ elsif missing_action == :warn_missing
+ $stderr.puts "Message #{mid} not found in index, skipping."
+ end
+
+ next
+ end
+
+ m = index.build_message mid
+ new_labels = labels.to_set_of_symbols
+
+ if m.labels == new_labels
+ puts "#{mid} unchanged" if opts[:verbose]
+ next
+ end
+
+ puts "Changing flags for #{mid} from '#{m.labels.to_a * ' '}' to '#{new_labels.to_a * ' '}'" if opts[:verbose]
+ num_changed += 1
+
+ next if opts[:dry_run]
+
+ m.labels = new_labels
+ index.update_message_state m
+ end
+
+ index.commit_transaction if opts[:atomic]
+ puts "Updated #{num_changed} of #{num_read} messages."
+rescue AbortExecution
+ index.cancel_transaction if opts[:atomic]
+ raise
+rescue Exception => e
+ index.cancel_transaction if opts[:atomic]
+ File.open("sup-exception-log.txt", "w") { |f| f.puts e.backtrace }
+ raise
+ensure
+ index.save_index unless opts[:atomic]
+ Redwood::finish
+ index.unlock
+end
diff --git a/bin/sup-server b/bin/sup-server
diff --git a/lib/sup/index.rb b/lib/sup/index.rb
@@ -260,6 +260,21 @@ EOS
end
end
+ # wrap all future changes inside a transaction so they're done atomically
+ def begin_transaction
+ synchronize { @xapian.begin_transaction }
+ end
+
+ # complete the transaction and write all previous changes to disk
+ def commit_transaction
+ synchronize { @xapian.commit_transaction }
+ end
+
+ # abort the transaction and revert all changes made since begin_transaction
+ def cancel_transaction
+ synchronize { @xapian.cancel_transaction }
+ end
+
## xapian-compact takes too long, so this is a no-op
## until we think of something better
def optimize