class Client :
# Setup class variables
client_keys = (public_key, private_key) # Public key private key tuple
operation = Operation('UPDATE ...') # Desired operation
message = Message(operation, retransmission = False) # Message containing operation and retransmission flag
message_handler = ClientMessageHandler(client_keys) # Handling messages and their signatures and calling timeout callbacks
olympus = Olympus() # Contains information about olympus e.g., how to send messages to olympus and its state
configuration = olympus.get_current_configuration() # Configuration consists of an ordered list of replicas and how to contact them
Timer.run(interval = 10, target = check_new_config(olympus)) # Check for new configuration every 10 seconds
# Send operation to head
def send_operation(head, operation) :
message_handler.send(receiver = head, message = operation)
# Handle message time out
def message_timeout(message) :
if message.retransmitted : # If already retransmissited, send reconfiguration request to olympus
message_handler.send(receiver = olympus, message = reconfiguration_request())
else : # Retransmit message
retransmit(message)
# Set message retransmitted flag and broadcast request to all nodes
def retransmit(message) :
message.retransmitted = True
message_handler.broadcast(configuration, message = operation)
# Runs after receiving a message, presumably the result
def receive_result(message) :
# Verification is done in ClientMessageHandler
# If error, request reconfiguration
if result == Error :
message_handler.send(receiver = olympus, message = reconfiguration_request())
else :
# Done
exit(0)
# This method is called periodically to check for new configuration
def check_new_config(olympus) :
config = olympus.get_current_configuration()
if self.configuration != config :
retransmit(operation)
# Run the client and send its request
def run() :
send_operation(configuration.Replicas.Head, operation)