aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Palfrader <peter@palfrader.org>2007-10-08 23:40:52 +0000
committerPeter Palfrader <peter@palfrader.org>2007-10-08 23:40:52 +0000
commitff19400cb0d8c558c6e7a8937cd759bc9a76d795 (patch)
tree09099ba42c4a5d222f629e4065b26734c6acef6e
parent11a782a6c3ae1d7becbc7895f5e896ed099c1d78 (diff)
downloadtor-ff19400cb0d8c558c6e7a8937cd759bc9a76d795.tar
tor-ff19400cb0d8c558c6e7a8937cd759bc9a76d795.tar.gz
Commit this stuff somewhere before I delete it accidentally
svn:r11794
-rwxr-xr-xcontrib/auto-naming/build-approved-routers22
-rw-r--r--contrib/auto-naming/create-db.sql29
-rw-r--r--contrib/auto-naming/db-config.rb6
-rw-r--r--contrib/auto-naming/db.rb145
-rwxr-xr-xcontrib/auto-naming/process-consensus94
-rwxr-xr-xcontrib/auto-naming/update-named-status.rb43
6 files changed, 339 insertions, 0 deletions
diff --git a/contrib/auto-naming/build-approved-routers b/contrib/auto-naming/build-approved-routers
new file mode 100755
index 000000000..dcc597e6f
--- /dev/null
+++ b/contrib/auto-naming/build-approved-routers
@@ -0,0 +1,22 @@
+#!/usr/bin/ruby
+
+require "yaml"
+
+require 'db'
+require 'db-config'
+
+verbose = ARGV.first == "-v"
+
+db = Db.new($CONFIG['database']['dbname'], $CONFIG['database']['user'], $CONFIG['database']['password'])
+
+db.transaction_begin
+named = db.query2("
+ SELECT fingerprint, router_id, nickname_id, nick, first_seen, last_seen
+ FROM router NATURAL JOIN router_claims_nickname NATURAL JOIN nickname
+ WHERE named")
+while (n=named.next) do
+ puts "# (r##{n['router_id']},n##{n['nickname_id']}); first_seen: #{n['first_seen']}, last_seen: #{n['last_seen']}"
+ fpr = n['fingerprint'].split(/(....)/).delete_if{|x| x=="" }.join(' ')
+ puts "#{n['nick']} #{fpr}}"
+end
+db.transaction_commit
diff --git a/contrib/auto-naming/create-db.sql b/contrib/auto-naming/create-db.sql
new file mode 100644
index 000000000..6377be3ea
--- /dev/null
+++ b/contrib/auto-naming/create-db.sql
@@ -0,0 +1,29 @@
+
+CREATE TABLE router (
+ router_id SERIAL PRIMARY KEY,
+ fingerprint CHAR(40) NOT NULL,
+ UNIQUE(fingerprint)
+);
+-- already created implicitly due to unique contraint
+-- CREATE INDEX router_fingerprint ON router(fingerprint);
+
+CREATE TABLE nickname (
+ nickname_id SERIAL PRIMARY KEY,
+ nick VARCHAR(30) NOT NULL,
+ UNIQUE(nick)
+);
+-- already created implicitly due to unique contraint
+-- CREATE INDEX nickname_nick ON nickname(nick);
+
+CREATE TABLE router_claims_nickname (
+ router_id INTEGER NOT NULL REFERENCES router(router_id) ON DELETE CASCADE,
+ nickname_id INTEGER NOT NULL REFERENCES nickname(nickname_id) ON DELETE CASCADE,
+ first_seen TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ last_seen TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ named BOOLEAN NOT NULL DEFAULT 'false',
+ UNIQUE(router_id, nickname_id)
+);
+CREATE INDEX router_claims_nickname_router_id ON router_claims_nickname(router_id);
+CREATE INDEX router_claims_nickname_nickname_id ON router_claims_nickname(nickname_id);
+CREATE INDEX router_claims_nickname_first_seen ON router_claims_nickname(first_seen);
+CREATE INDEX router_claims_nickname_last_seen ON router_claims_nickname(last_seen);
diff --git a/contrib/auto-naming/db-config.rb b/contrib/auto-naming/db-config.rb
new file mode 100644
index 000000000..3cf2dbe32
--- /dev/null
+++ b/contrib/auto-naming/db-config.rb
@@ -0,0 +1,6 @@
+$CONFIG = {} unless $CONFIG
+$CONFIG['database'] = {} unless $CONFIG['database']
+
+$CONFIG['database']['dbname'] = 'tornaming';
+$CONFIG['database']['user'] = 'tornaming';
+$CONFIG['database']['password'] = 'x';
diff --git a/contrib/auto-naming/db.rb b/contrib/auto-naming/db.rb
new file mode 100644
index 000000000..706e81c39
--- /dev/null
+++ b/contrib/auto-naming/db.rb
@@ -0,0 +1,145 @@
+#!/usr/bin/ruby
+
+require "dbi"
+
+class WeaselDbQueryHandle
+ def initialize(sth)
+ @sth = sth
+ end
+
+ def next()
+ row = @sth.fetch_hash
+ if row
+ return row
+ else
+ @sth.finish
+ return nil
+ end
+ end
+end
+
+class Db
+ def initialize(database, user, password)
+ @dbh = DBI.connect("dbi:Pg:#{database}:localhost", user, password);
+ @dbh['AutoCommit'] = false
+ @transaction = false
+ @pre_initial_transaction=true
+ end
+
+ def do(query,*args)
+ @dbh.do(query,*args)
+ end
+ def transaction_begin()
+ @dbh.do("BEGIN") unless @pre_initial_transaction
+ @transaction = true
+ @pre_initial_transaction=false
+ end
+ def transaction_commit()
+ @dbh.do("COMMIT")
+ @transaction = false
+ end
+ def transaction_rollback()
+ @dbh.do("ROLLBACK")
+ end
+ def get_primarykey_name(table);
+ #return 'ref';
+ return table+'_id';
+ end
+
+ def update(table, values, keys)
+ cols = []
+ vals = []
+ values.each_pair{ |k,v|
+ cols << "#{k}=?"
+ vals << v
+ }
+
+ wheres = []
+ keys.each_pair{ |k,v|
+ wheres << "#{k}=?"
+ vals << v
+ }
+
+ throw "update value set empty" unless cols.size > 0
+ throw "where clause empty" unless wheres.size > 0
+
+ query = "UPDATE #{table} SET #{cols.join(',')} WHERE #{wheres.join(' AND ')}"
+ transaction_begin unless transaction_before=@transaction
+ r = @dbh.do(query, *vals)
+ transaction_commit unless transaction_before
+ return r
+ end
+
+ def update_row(table, values)
+ pk_name = get_primarykey_name(table);
+ throw "Ref not defined" unless values[pk_name]
+ return update(table, values.clone.delete_if{|k,v| k == pk_name}, { pk_name => values[pk_name] });
+ end
+ def insert(table, values)
+ cols = values.keys
+ vals = values.values
+ qmarks = values.values.collect{ '?' }
+
+ query = "INSERT INTO #{table} (#{cols.join(',')}) VALUES (#{qmarks.join(',')})"
+ transaction_begin unless transaction_before=@transaction
+ @dbh.do(query, *vals)
+ transaction_commit unless transaction_before
+ end
+
+ def insert_row(table, values)
+ pk_name = get_primarykey_name(table);
+ if values[pk_name]
+ insert(table, values)
+ else
+ transaction_begin unless transaction_before=@transaction
+ row = query_row("SELECT nextval(pg_get_serial_sequence('#{table}', '#{pk_name}')) AS newref");
+ throw "No newref?" unless row['newref']
+ values[pk_name] = row['newref']
+ insert(table, values);
+ transaction_commit unless transaction_before
+ end
+ end
+ def delete_row(table, ref)
+ pk_name = get_primarykey_name(table);
+ query = "DELETE FROM #{table} WHERE #{pk_name}=?"
+ transaction_begin unless transaction_before=@transaction
+ @dbh.do(query, ref)
+ transaction_commit unless transaction_before
+ end
+ def query(query, *params)
+ sth = @dbh.execute(query, *params)
+ while row = sth.fetch_hash
+ yield row
+ end
+ sth.finish
+ end
+ # nil if no results
+ # hash if one match
+ # throw otherwise
+ def query_row(query, *params)
+ sth = @dbh.execute(query, *params)
+
+ row = sth.fetch_hash
+ if row == nil
+ sth.finish
+ return nil
+ elsif sth.fetch_hash != nil
+ sth.finish
+ throw "More than one result when querying for #{query}"
+ else
+ sth.finish
+ return row
+ end
+ end
+ def query_all(query, *params)
+ sth = @dbh.execute(query, *params)
+
+ rows = sth.fetch_all
+ return nil if rows.size == 0
+ return rows
+ end
+ def query2(query, *params)
+ sth = @dbh.execute(query, *params)
+ return WeaselDbQueryHandle.new(sth)
+ end
+end
diff --git a/contrib/auto-naming/process-consensus b/contrib/auto-naming/process-consensus
new file mode 100755
index 000000000..321b64dfb
--- /dev/null
+++ b/contrib/auto-naming/process-consensus
@@ -0,0 +1,94 @@
+#!/usr/bin/ruby
+
+require "yaml"
+
+require 'db'
+require 'db-config'
+require 'update-named-status'
+
+$db = Db.new($CONFIG['database']['dbname'], $CONFIG['database']['user'], $CONFIG['database']['password'])
+
+$router_cache = {}
+$nickname_cache = {}
+
+def parse_consensus consensus
+ ts = nil
+ routers = []
+ consensus.each do |line|
+ (key, value) = line.split(' ',2)
+ case key
+ when "valid-after", "published": ts = DateTime.parse(value)
+ when "r":
+ (nick, fpr, _) = value.split(' ', 3)
+ nick.downcase!
+ next if nick == 'unnamed'
+ routers << {
+ 'nick' => nick,
+ 'fingerprint' => (fpr+'=').unpack('m').first.unpack('H*').first
+ }
+ end
+ end
+ throw "Did not find a timestamp" unless ts
+ throw "Did not find any routers" unless routers.size > 0
+ return ts, routers
+end
+
+def insert_routers_into_db(router, table, field, value)
+ pk = table+'_id'
+ row = $db.query_row("SELECT #{pk} FROM #{table} WHERE #{field}=?", value)
+ if row
+ return row[pk]
+ else
+ r = { field => value }
+ $db.insert_row( table, r )
+ return r[pk]
+ end
+end
+
+def handle_one_consensus(c)
+ puts "parsing..." if $verbose
+ timestamp, routers = parse_consensus c
+ puts "storing..." if $verbose
+
+ routers.each do |router|
+ fpr = router['fingerprint']
+ nick = router['nick']
+ $router_cache[fpr] = router_id = ($router_cache[fpr] or insert_routers_into_db(router, 'router', 'fingerprint', router['fingerprint']))
+ $nickname_cache[nick] = nickname_id = ($nickname_cache[nick] or insert_routers_into_db(router, 'nickname', 'nick', router['nick']))
+
+ row = $db.update(
+ 'router_claims_nickname',
+ { 'last_seen' => timestamp.to_s },
+ { 'router_id' => router_id, 'nickname_id' => nickname_id} )
+ case row
+ when 0:
+ $db.insert('router_claims_nickname',
+ {
+ 'first_seen' => timestamp.to_s,
+ 'last_seen' => timestamp.to_s,
+ 'router_id' => router_id, 'nickname_id' => nickname_id} )
+ when 1:
+ else
+ throw "Update of router_claims_nickname returned unexpected number of affected rows(#{row})"
+ end
+ end
+end
+
+$db.transaction_begin
+if ARGV.first == '-v'
+ $verbose = true
+ ARGV.shift
+end
+
+if ARGV.size == 0
+ handle_one_consensus STDIN.readlines
+ do_update true
+else
+ ARGV.each do |filename|
+ puts filename if $verbose
+ handle_one_consensus File.new(filename).readlines
+ puts "updating..." if $verbose
+ do_update $verbose
+ end
+end
+$db.transaction_commit
diff --git a/contrib/auto-naming/update-named-status.rb b/contrib/auto-naming/update-named-status.rb
new file mode 100755
index 000000000..8ff60ca68
--- /dev/null
+++ b/contrib/auto-naming/update-named-status.rb
@@ -0,0 +1,43 @@
+#!/usr/bin/ruby
+
+require "yaml"
+
+require 'db'
+require 'db-config'
+
+def do_update verbose
+ now = "TIMESTAMP '" + $db.query_row("SELECT max(last_seen) AS max FROM router_claims_nickname")['max'].to_s + "'"
+
+ denamed = $db.do("
+ UPDATE router_claims_nickname
+ SET named=false
+ WHERE named
+ AND last_seen < #{now} - INTERVAL '6 months'")
+ puts "de-named: #{denamed}" if verbose
+
+ named = $db.do("
+ UPDATE router_claims_nickname
+ SET named=true
+ WHERE NOT named
+ AND first_seen < #{now} - INTERVAL '2 weeks'
+ AND last_seen > #{now} - INTERVAL '2 days'
+ AND NOT EXISTS (SELECT *
+ FROM router_claims_nickname AS innertable
+ WHERE named
+ AND router_claims_nickname.nickname_id=innertable.nickname_id) "+ # if that nickname is already named, we lose.
+ " AND NOT EXISTS (SELECT *
+ FROM router_claims_nickname AS innertable
+ WHERE router_claims_nickname.nickname_id=innertable.nickname_id
+ AND router_claims_nickname.router_id <> innertable.router_id
+ AND last_seen > #{now} - INTERVAL '1 month') ") # if nobody else wanted that nickname in the last month we are set
+ puts "named: #{named}" if verbose
+end
+
+if __FILE__ == $0
+ $db = Db.new($CONFIG['database']['dbname'], $CONFIG['database']['user'], $CONFIG['database']['password'])
+ verbose = ARGV.first == "-v"
+
+ $db.transaction_begin
+ do_update verbose
+ $db.transaction_commit
+end