Skip to content
Snippets Groups Projects
Commit 2df2bec2 authored by Dixon Tirtayadi's avatar Dixon Tirtayadi
Browse files

Client done and change message to UDP

parent 588d458f
No related branches found
No related tags found
No related merge requests found
File added
File added
File added
File added
File added
import socket, sys
import pickle
import json
from message import * # Can change this after testing done
import paxos
# Client to send lock / unlock to servers
class Client:
def __init__(self, server_addrs) -> None:
self.server_addrs = server_addrs
# Returns true if lock is successful, false otherwise
# x : value to lock (int)
def lock(self, x) -> bool:
json = {"op": "lock", "value": x}
for server_addr in self.server_addrs:
pass
# Send JSON to servers, will be treated as command
# Wait for response to return
# Returns true if unlock is successful, false otherwise
# x : value to lock (int)
def unlock(self, x) -> bool:
json = {"op": "unlock", "value": x}
for server_addr in self.server_addrs:
pass
# Send JSON to servers, will be treated as command
# Wait for response to return
# # Client to send lock / unlock to servers
# class Client:
# def __init__(self, server_addrs) -> None:
# self.server_addrs = server_addrs
# # Returns true if lock is successful, false otherwise
# # x : value to lock (int)
# def lock(self, x) -> bool:
# json = {"op": "lock", "value": x}
# for server_addr in self.server_addrs:
# pass
# # Send JSON to servers, will be treated as command
# # Wait for response to return
# # Returns true if unlock is successful, false otherwise
# # x : value to lock (int)
# def unlock(self, x) -> bool:
# json = {"op": "unlock", "value": x}
# for server_addr in self.server_addrs:
# pass
# # Send JSON to servers, will be treated as command
# # Wait for response to return
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
paxos_req = PaxosRequest((HOST, PORT), LockCommand("lock", 0))
# paxos_req = P1A((HOST, PORT), paxos.BallotNumber(2, (HOST, PORT)))
data = pickle.dumps(paxos_req)
print(paxos_req, "\n")
print(data, "\n")
de_paxos_req = pickle.loads(data)
print(de_paxos_req, "\n")
#data = " ".join(sys.argv[1:])
#print('data = %s' %data)
# create a TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# create a UDP socket
HOST, PORT = "localhost", 9000
# TODO: Uncomment below for multiple nodes paxos
# serv_addresses = ((HOST, PORT), (HOST, PORT + 1), (HOST, PORT + 2))
serv_addresses = ((HOST, PORT), )
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('localhost', 0))
address = sock.getsockname()
print("Starting client {0}".format(address))
input_str = input("Enter a command: ") # Input would be "lock 2" / "unlock 1", etc
try:
# connect to server
sock.connect((HOST, PORT))
while input_str != "exit":
lock, val = input_str.split(" ", 2)
paxos_req = PaxosRequest(address, LockCommand(lock, val))
data = pickle.dumps(paxos_req)
print("Sending lock command {}".format(paxos_req))
# send request to server
for serv_addr in serv_addresses:
sock.sendto(data, serv_addr)
# send data
#sock.sendall(bytes(data + "\n"))
sock.sendall(data)
# receive data back from the server
res = pickle.loads(sock.recv(1024))
# receive data back from the server
received = sock.recv(1024)
print("Received response: {}".format(res))
if res.value == True:
print("Command is successfully run")
else:
print("Command is failed to run")
input_str = input("\nEnter a command: ")
finally:
# shut down
# Close socket
sock.close()
print("Sent: {}".format(data))
print("Received: {}".format(str(received)))
print("Received Deserialize: {}".format(pickle.loads(received)))
from message import LockCommand
from paxos_utils import Address
from typing import Dict
......@@ -10,6 +11,7 @@ class LockManager:
# a locks it already has, false otherwise
def lock(self, value: int, client: Address) -> bool:
# acquire lock
print("Locking {0} for {1}".format(value, client))
if value not in self.locks:
self.locks[value] = client
return True
......@@ -23,6 +25,7 @@ class LockManager:
# returns true if lock is unlocked, false otherwise
def unlock(self, value: int, client: Address) -> bool:
print("Unlocking {0} for {1}".format(value, client))
# lock does not exist
if value not in self.locks:
return False
......@@ -36,6 +39,16 @@ class LockManager:
return True
def execute(self, lock_command: LockCommand, client_address: Address) -> bool:
lock_res = False
if lock_command.op == "lock":
lock_res = self.lock(int(lock_command.value), client_address)
elif lock_command.op == "unlock":
lock_res = self.unlock(int(lock_command.value), client_address)
print("Current Locks: {}".format(self.locks))
return lock_res
# quick_test
#if __name__ == "__main__":
......
......@@ -38,7 +38,7 @@ class P1A(Message):
self.ballot_num: BallotNumber = ballot_num
def __str__(self) -> str:
return f"P1A({super().__str__()}, {str(self.ballot_num)})\n"
return f"P1A({super().__str__()}, {str(self.ballot_num)})"
class P1B(Message):
......@@ -50,7 +50,7 @@ class P1B(Message):
self.accepted: Dict[int, BallotValuePair] = accepted
def __str__(self) -> str:
return f"P1B({super().__str__()}, {str(self.accepted_ballot)}, {str(self.accepted)})\n"
return f"P1B({super().__str__()}, {str(self.accepted_ballot)}, {str(self.accepted)})"
class P2A(Message):
......@@ -64,7 +64,7 @@ class P2A(Message):
self.value: PaxosRequest = value
def __str__(self) -> str:
return f"P2A({super().__str__()}, {str(self.ballot_num)}, slot_num: {str(self.slot_num)}, value: {str(self.value)})\n"
return f"P2A({super().__str__()}, {str(self.ballot_num)}, slot_num: {str(self.slot_num)}, value: {str(self.value)})"
class P2B(Message):
......@@ -76,7 +76,7 @@ class P2B(Message):
self.slot_num: int = slot_num
def __str__(self) -> str:
return f"P2B({super().__str__()}, {str(self.ballot_num)}, slot_num: {str(self.slot_num)})\n"
return f"P2B({super().__str__()}, {str(self.ballot_num)}, slot_num: {str(self.slot_num)})"
## Client messages=, separate into a new class
......@@ -87,7 +87,7 @@ class PaxosRequest(Message):
self.lock_command: LockCommand = lock_command
def __str__(self) -> str:
return f"PaxosRequest({super().__str__()}, {str(self.lock_command)})\n"
return f"PaxosRequest({super().__str__()}, {str(self.lock_command)})"
class PaxosResult(Message):
......@@ -96,7 +96,7 @@ class PaxosResult(Message):
self.value: bool = value
def __str__(self) -> str:
return f"PaxosResult({super().__str__()}, value: {str(self.value)})\n"
return f"PaxosResult({super().__str__()}, value: {str(self.value)})"
class LockCommand:
......
......@@ -13,7 +13,7 @@ from collections import defaultdict
# Paxos servers
class Paxos(socketserver.TCPServer):
class Paxos(socketserver.UDPServer):
def __init__(self, address, servers) -> None:
self.address: Address = address # Our address tuple (ip, port)
......@@ -76,7 +76,8 @@ class PaxosHandler(socketserver.BaseRequestHandler):
# Use self.server.arg to get servers fields
# Note that we guarantee communication client to server is exactly once,
# no need to worry about duplicate request and proposing two slot.
data = self.request.recv(1024).strip() # DEBUG LOG
data = self.request[0].strip()
# data = self.request.recv(1024).strip() # DEBUG LOG
print("{} wrote:".format(self.client_address)) # DEBUG LOG
print(data) # DEBUG LOG
......@@ -155,18 +156,15 @@ class PaxosHandler(socketserver.BaseRequestHandler):
if len(self.server.slot_to_acceptors[p2a.slot_num]) > (len(self.server.servers)/2):
#Majority accepted, can put into log
self.server.log[p2a.slot_num] = bvp
self.request.sendall(pickle.dumps(PaxosResult((HOST, 12345), True)))
# TODO: Executelog() function
# executeLog();
# Testing code to return the PaxosResult (TODO: Put this inside executeLog instead of here)
lock_res = self.server.lock_manager.execute(paxos_req.lock_command, self.client_address)
# Testing code to return the PaxosResult
lock_res = False
if paxos_req.lock_command == "lock":
lock_res = self.server.lock_manager.lock(self.client_address, int(paxos_req.lock_command.value))
else: # unlock
lock_res = self.server.lock_manager.unlock(self.client_address, int(paxos_req.lock_command.value))
sock = self.request[1]
sock.sendto(pickle.dumps(PaxosResult(sock.getsockname(), lock_res)), sender)
self.request.sendall(pickle.dumps(PaxosResult((HOST, 12345), lock_res)))
def handleP1A(self, p1a, sender):
if self.server.highest_ballot_seen < p1a.ballot_num:
......@@ -419,32 +417,19 @@ class PaxosHandler(socketserver.BaseRequestHandler):
# Serialize obj, and send the message.
# This function will not wait for reply (communication between paxos nodes)
def send_msg(obj, dest_addr: Address):
HOST, PORT = dest_addr
print("Sending {0} to {1}".format(obj, dest_addr))
data = pickle.dumps(obj)
print(obj, "\n")
print(data, "\n")
de_paxos_req = pickle.loads(data)
print(de_paxos_req, "\n")
#data = " ".join(sys.argv[1:])
#print('data = %s' %data)
# create a TCP socket
# TODO: Between paxos dont use TCP? Use UDP instead? TCP will make it does not drop any packet right?
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# connect to server
sock.connect((HOST, PORT))
# send data
#sock.sendall(bytes(data + "\n"))
sock.sendall(data)
finally:
# shut down
sock.close()
# print(obj, "\n")
# print(data, "\n")
# de_paxos_req = pickle.loads(data)
# print(de_paxos_req, "\n")
# Send a packet using UDP
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(data, dest_addr)
sock.close()
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
HOST, PORT = "localhost", 9000
# addresses = ((HOST, PORT), (HOST, PORT + 1), (HOST, PORT + 2))
addresses = ((HOST, PORT),)
# Create the server, binding to localhost on port 9999
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment