-
Notifications
You must be signed in to change notification settings - Fork 0
Refactoring
Leberwurscht edited this page Feb 28, 2012
·
91 revisions
WebServer [IMPLEMENTED] (webserver.py)
...
ControlSample [IMPLEMENTED] [mapped with sqlalchemy.ext.declarative] (partners.py)
partner_id
timestamp
penalty (=1 for offense, =0 for no offense, =NULL if partner was de-kicked manually)
offense (only necessary if penalty!=0)
webfinger_address (only necessary if penalty!=0, needed because only one offense per webfinger address must be counted to prevent profile owners from getting servers kicked)
Violation [IMPLEMENTED] [mapped with sqlalchemy.ext.declarative] (partners.py)
partner_id
timestamp
description
Partner [IMPLEMENTED] [provide sqlalchemy mapper for this class] (partners.py)
name # may not contain newline
accept_password # may not contain newline
address
control_probability
last_connection
kicked
connection_schedule (determines connection direction: if this field is "", partner is a client)
provide_username # may not contain newline
provide_password # may not contain newline
__init__(partner_name, accept_password, base_url, control_probability, connection_schedule, provide_username, provide_password)
get_synchronization_address()
control_sample():
if self==MySelf: return False
else random
PartnerDatabase [IMPLEMENTED] (partners.py)
cleanup()
delete old saved control samples
register_control_sample(partner_name, webfinger_address=str, offense=None/str)
register_violation(partner_name, violation)
register_connection(partner_name)
get_partners()
get_partner(partner_name):
must return None only if partner_name==None, as this is the representation for our own server
save_partner(partner)
delete_partner(partner_name)
Profile [IMPLEMENTED] (states.py)
full_name
hometown
country_code
services
submission_timestamp
captcha_signature
Message(abstract): [IMPLEMENTED] (synchronization.py)
transmit()
@classmethod receive()
Ghost [IMPLEMENTED] [provide sqlalchemy mapper for this class] (states.py)
retrieval_timestamp (=None means profile expired)
hash
DeleteMessage(Message): [IMPLEMENTED] (synchronization.py)
retrieval_timestamp (=None means that partner won't take responsibility) / TODO: rename?
hash
transmit(partnersocket)
@classmethod receive(partnersocket)
State(Message) [IMPLEMENTED] [provide sqlalchemy mapper for this class, but require Profile/retrieval_timestamp != None] (states.py)
webfinger_address
retrieval_timestamp (=None means that partner won't take responsibility)
Profile (mapped with "Composite Column Types")
hash (read-only-property)
@classmethod retrieve(address):
...
run self.validate(), return None on failure
==(): # assumption: retrieval_timestamp!=None, same address
Profile==None for both || same hash
assert_validity(reference_timestamp=now): # assumption: retrieval_timestamp!=None
(!) self.retrieval_timestamp<=reference_timestamp
(!) self.retrieval_timestamp > reference_timestamp - RESPONSIBILITY_TIMESPAN[rename!]
for Profile!=None:
(!) state.retrieval_timestamp>state.submission_timestamp
(!) state.submission_timestamp <= reference_timestamp
(!) not expired
(!) captcha signature
There are three roles that the State class can take over:
- retrieval_timestamp==None, Profile==None: if this is transmitted by a partner, this means that the partner knows that the profile has changed, but can't take responsibility because it was retrieved a too long time ago. The address must be added to the submission_queue.
- retrieval_timestamp!=None, Profile==None: if this is transmitted by a partner, he tells us that the profile does not exists anymore/is invalid, and takes responsibility for this information.
- retrieval_timestamp!=None, Profile!=None: if this is transmitted by a partner, he tells us that the profile has changed and he tells us the new content. The partner takes responsibility for this information. For such a state, the hash attribute can be read, and the state can be saved to the database.
.
HashTrie [IMPLEMENTED] (hashtrie.py)
database_path
lock
trieserver (the Popened server process)
__init__(path, erase=False)
get_missing_hashes_as_server(socket)
get_missing_hashes_as_client(socket)
delete()
add()
close(erase=False)
StateDatabase [IMPLEMENTED] (states.py)
database_path
Session
hashtrie
lock
cleanup_timestamp # initialized in __init__
cleanup()
update cleanup_timestamp in variables table
search()
save(state):
ValidState => add, (delete old one)
(!) respect RESUBMISSION_INTERVAL when old Profile exists
(!) Profile newer than old Profile
InvalidState => delete
get_ghosts(list of missing hashes)
get_invalid_state(binhash, timestamp):
find webfinger address for binhash from database
return a State(address=webfinger_address, retrieval_timestamp=timestamp, profile=None)
get_valid_state(binhash):
get state from states table
if retrieval_timestamp too old:
state.Profile := None
state.retrieval_timestamp := None
return state
else:
return state
close()
Claim [IMPLEMENTED] (context.py)
timestamp=time.time()
state
partner_name (=None means claim is made by ourselves)
__cmp__():
MySelf > other partners
timestamp
validate():
if partner:
(!) partner not kicked
if partner.control_sample():
partner.register_control_sample()
retrieved_state := State.retrieve(address)
if not state==retrieved_state:
offense := Offense(state, retrieved_state)
partner <- offense
state = retrieved_state
partner = None
try:
state.validate()
make sure self.address==profile.address
except Violation, violation:
if partner:
partner <- violation
return None
return state
Submission: [IMPLEMENTED] (context.py)
webfinger_address
Context: [IMPLEMENTED] (context.py)
statedb
partnerdb
submission_queue
validation_queue
assimilation_queue
synchronization_address
logger
submit_address(webfinger_address)
process_state(state, partner_name):
if state.retrieval_timestamp: # partner takes responsibility
claim := Claim(state, partner_name)
put into validation queue
else: # partner does not take responsibility
put state.address into submission queue
synchronize_as_server(partnersocket, partner_name)
synchronize_as_client(partnersocket, partner_name)
Application: [IMPLEMENTED] (sduds.py)
ready_for_synchronization (threading.Event)
start()
terminate()
synchronize_with_partner()