class Client(object): """ Client object """ def __init__(self, client_id, server_host, server_port, mc_address, mc_port, send_interval=5, chunk_size=10000000, file_size=10000000 * 2, run_time=30, test_path='./', dd_method=False): """ :param client_id: string, unique id for the client :param server_host: string, ip address/hostname for sever :param server_host: string, port server will listen on :param mc_address: string, multicast group address to publish heartbeat :param mc_port: int, port for multicast group :param send_interval: int, heartbeat send interval :param chunk_size: int, in bytes, the size to data size to write to a file at a time :param file_size: int, maximum file size for the writer :param run_time: int, self explanatory, ya know :param test_path: string, path to write the data files :param dd_method: bool, use dd or not for the file writing """ self.client_id = client_id self.server_host = server_host self.chunk_size = chunk_size self.file_size = file_size self.run_time = run_time self.mc_group = mc_address, mc_port self.send_interval = send_interval self.test_path = test_path # if dd_method is True, dd will be used # if dd_method is False, python file object will be used self.dd_method = dd_method logging.basicConfig(filename=client_id + '.log', format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO) # Unsure on requirements, going to assume worst case # Need to check to see if the chunk size and # run time will allow two instances of the time to be written try: # check to see if two chunks can be written to the file assert self.file_size / self.chunk_size >= 2 except AssertionError: print "Client chunk size is too small for max file size." \ "Please reconfigure" exit(1) # Create the initial TCP connection self.tcp = TCPClient((server_host, server_port)) self.hb1 = Heartbeat(self.mc_group[0], self.mc_group[1], self.client_id, self.send_interval) self.kill_sig = Queue(1) self.hb_process = Process(target=self.hb1.run, args=(self.kill_sig, )) self.hb_process.daemon = True self.queue1 = Queue() dw1 = DataWriter(self.chunk_size, self.file_size, self.dd_method, self.test_path) self.dw_process = Process(target=dw1.run, args=(self.queue1, self.kill_sig)) self.dw_process.daemon = True self.dw_process_pid = None def start_client(self): """ start the client """ thread.start_new_thread(self.monitor, ()) thread.start_new_thread(self.run_timer, ()) self.hb_process.start() self.start_writer() def start_writer(self): """ start the data writer """ # Start the process for the data writing, chunking, thing, self.dw_process.start() self.dw_process_pid = self.dw_process.pid try: while self.kill_sig.empty(): try: dw_res = self.queue1.get(block=False) except Queue2.Empty: continue self.tcp.send_data(json.JSONEncoder().encode({ self.client_id: { "operation_time": dw_res[0], "file_size": dw_res[1], "chunk_size": self.chunk_size, "write_speed": dw_res[2] } })) logging.info(dw_res) except KeyboardInterrupt: pass finally: print "Closing Client" # ensure files were deleted self.kill_sig.put(True) self.dw_process.join() logging.info("Client shutting down") exit(0) def monitor(self): """ monitor the data writier """ try: while self.kill_sig.empty(): if self.dw_process_pid: # Probably not the best way... time.sleep(10) monitor_m = check_output([ 'ps', 'p', str(self.dw_process_pid), '-o', '%cpu,%mem' ], stderr=STDOUT) cpu, mem = monitor_m.splitlines()[1].strip().split() self.tcp.send_data(json.JSONEncoder().encode({ self.client_id + '_Performance': { "cpu": cpu, "mem": mem } })) except KeyboardInterrupt: pass def run_timer(self): """ run timer """ timer = 0 while timer < self.run_time: time.sleep(1) timer += 1 print "Timer ran out" self.tcp.close() self.hb1.close() self.kill_sig.put(True)