def actually_run_the_daemon(options): verbose = options.verbose chan = Channel(BUFSIZE) string = None (cnx, addr) = (None, None) string = socket.socket(socket.AF_INET, socket.SOCK_STREAM) string.bind(('', options.port)) string.listen(1) try: running = True while running: print("\nWAITING FOR CONNECTION") # DEBUG cnx, addr = string.accept() try: accept_msg = "CONNECTION FROM %s" % str(addr) if verbose: print(accept_msg) print("BRANCH TO options.accessLog.log()") sys.stdout.flush() options.access_log.log(accept_msg) print("BACK FROM options.access.log()") sys.stdout.flush() while 1: chan.clear() # print "BRANCH TO recvFromCnx" ; sys.stdout.flush() msg_ndx = recv_from_cnx(cnx, chan) # may raise exception (msg, real_ndx) = MsgImpl.read(chan, STR_OBJ_MODEL) # print " MSG_NDX: CALCULATED %s, REAL %s" % ( # msgNdx, realNdx) # switch on message type if msg_ndx == 0: print("GOT ZONE MISMATCH MSG") print(" timestamp %s" % msg.timestamp) print(" seqNbr %s" % msg.seq_nbr) print(" zoneName %s" % msg.zone_name) print(" expectedSerial %s" % msg.expected_serial) print(" actualSerial %s" % msg.actual_serial) text =\ "mismatch, domain %s: expected serial %s, got %s" % ( msg.zone_name, msg.expected_serial, msg.actual_serial) options.alertz_log.log(text) elif msg_ndx == 1: # timestamp, seqNb print("GOT CORRUPT LIST MSG") print(" timestamp %s" % msg.timestamp) print(" seqNbr %s" % msg.seq_nbr) text = "corrupt list: %s" % (msg.seq_nbr) options.alertz_log.log(text) elif msg_ndx == 2: # has one field, remarks print("GOT SHUTDOWN MSG") print(" remarks %s" % msg.remarks) running = False string.close() # XXX STUB: log the message text = "shutdown: %s" % (msg.remarks) options.alertz_log.log(text) cnx.close() break # permit only one message/cnx except KeyboardInterrupt as k_exc: print("<keyboard interrupt received while connection open>") if cnx: cnx.close() running = False except KeyboardInterrupt as k_exc: print("<keyboard interrupt received while listening>") # listening socket will be closed finally: if cnx: cnx.close() if string: string.close() # COMMENTING THIS OUT PREVENTS SEGFAULT ON STOCKTON --------- # if options.logMgr is not None: # options.logMgr.close() # options.logMgr = None # END COMMENTING OUT ---------------------------------------- if options.lock_mgr is not None: options.lock_mgr.unlock() options.lock_mgr = None
def actually_run_the_daemon(options): """ All necessary resources having been obtained, actually runs the daemon. """ verbose = options.verbose chan = Channel(BUFSIZE) skt = None (cnx, addr) = (None, None) skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM) skt.bind(('', options.port)) skt.listen(1) try: running = True while running: print("\nWAITING FOR CONNECTION") # DEBUG cnx, addr = skt.accept() try: accept_msg = "CONNECTION FROM %s" % str(addr) if verbose: print(accept_msg) print("BRANCH TO options.accessLog.log()") sys.stdout.flush() options.access_log.log(accept_msg) print("BACK FROM options.access.log()") sys.stdout.flush() while True: chan.clear() # print "BRANCH TO recvFromCnx" ; sys.stdout.flush() msg_ndx = recv_from_cnx(cnx, chan) # may raise exception # XXX s_obj_model (the former sOM) is UNDEFINIED here (msg, real_ndx) = MsgImpl.read(chan, s_obj_model) # DEBUG print(" MSG_NDX: CALCULATED %s, REAL %s" % ( msg_ndx, real_ndx)) # END # switch on message type if msg_ndx == 0: print("GOT ZONE MISMATCH MSG") # pylint: disable=no-member print(" timestamp %s" % msg.timestamp) # pylint: disable=no-member print(" seq_nbr %s" % msg.seq_nbr) # pylint: disable=no-member print(" zone_name %s" % msg.zone_name) # pylint: disable=no-member print(" expected_serial %s" % msg.expected_serial) # pylint: disable=no-member print(" /Serial %s" % msg.actual_serial) # pylint: disable=no-member text = \ "mismatch, domain %s: expected serial %s, got %s" % ( msg.zone_name, msg.expected_serial, msg.actual_serial) options.alertz_log.log(text) elif msg_ndx == 1: # timestamp, seq_nbr print("GOT CORRUPT LIST MSG") # pylint: disable=no-member print(" timestamp %s" % msg.timestamp) # pylint: disable=no-member print(" seq_nbr %s" % msg.seq_nbr) # pylint: disable=no-member text = "corrupt list: %s" % (msg.seq_nbr) options.alertz_log.log(text) elif msg_ndx == 2: # has one field, remarks print("GOT SHUTDOWN MSG") # pylint: disable=no-member print(" remarks %s" % msg.remarks) running = False skt.close() # XXX STUB: log the message # pylint: disable=no-member text = "shutdown: %s" % (msg.remarks) options.alertz_log.log(text) cnx.close() break # permit only one message/cnx except KeyboardInterrupt: print("<keyboard interrupt received while connection open>") if cnx: cnx.close() running = False except KeyboardInterrupt: print("<keyboard interrupt received while listening>") # listening socket will be closed finally: if cnx: cnx.close() if skt: skt.close()
def do_test_ack(self, text): # Create a channel ------------------------------------------ # its buffer will be used for both serializing # the instance # data and, by deserializing it, for creating a second instance. chan = Channel(BUFSIZE) buf = chan.buffer self.assertEqual(BUFSIZE, len(buf)) # create the ack_msg_cls class ------------------------------ ack_spec = self.s_obj_model.msgs[0] msg_name = ack_spec.name self.assertEqual('ack', msg_name) ack_msg_cls = make_msg_class(self.s_obj_model, 'ack') # create a message instance --------------------------------- values = [text] ack = ack_msg_cls(values) (_) = tuple(values) # WAS text1 # pylint: disable=no-member self.assertEqual(ack_spec.name, ack.name) # we don't have any nested enums or messages # pylint: disable=no-member self.assertEqual(0, len(ack.enums)) # pylint: disable=no-member self.assertEqual(0, len(ack.msgs)) # pylint: disable=no-member self.assertEqual(1, len(ack.fieldClasses)) self.assertEqual(1, len(ack)) # number of fields in instance for ndx, value in enumerate(ack): self.assertEqual(values[ndx], value) # verify fields are accessible in the object ---------------- # pylint: disable=no-member self.assertEqual(text, ack.text) # serialize the object to the channel ----------------------- buf = chan.buffer chan.clear() nnn = ack.write_stand_alone(chan) self.assertEqual(0, nnn) # returns msg index chan.flip() print("ACTUAL LENGTH OF SERIALIZED ACK OBJECT: %u" % chan.limit) # deserialize the channel, making a clone of the message ---- (readback, _) = MsgImpl.read(chan, self.s_obj_model) self.assertIsNotNone(readback) self.assertTrue(ack.__eq__(readback)) # produce another message from the same values -------------- ack2 = ack_msg_cls(values) chan2 = Channel(BUFSIZE) nnn = ack2.write_stand_alone(chan2) chan2.flip() (copy2, nn3) = ack_msg_cls.read(chan2, self.s_obj_model) self.assertTrue(ack.__eq__(readback)) self.assertTrue(ack2.__eq__(copy2)) self.assertEqual(nnn, nn3) # GEEP
def test_le_msg_serialization(self): # parse the protoSpec # XXX highly questionable: # verify that this adds 1 (msg) + 5 (field count) to the number # of entries in getters, putters, etc self.assertIsNotNone(self.s_obj_model) self.assertTrue(isinstance(self.s_obj_model, M.ProtoSpec)) self.assertEqual('org.xlattice.ringd', self.s_obj_model.name) self.assertEqual(0, len(self.s_obj_model.enums)) self.assertEqual(11, len(self.s_obj_model.msgs)) self.assertEqual(0, len(self.s_obj_model.seqs)) # XXX a foolish test, but we use the variable 'leMsgSpec' below le_msg_spec = self.s_obj_model.msgs[5] msg_name = le_msg_spec.name self.assertEqual('logEntry', msg_name) # Create a channel ------------------------------------------ # its buffer will be used for both serializing # the instance # data and, by deserializing it, for creating a second instance. chan = Channel(BUFSIZE) buf = chan.buffer self.assertEqual(BUFSIZE, len(buf)) # create the LogEntryMsg class ------------------------------ log_entry_msg = make_msg_class(self.s_obj_model, 'logEntry') # create a message instance --------------------------------- values = self.le_msg_values() # a list of quasi-random values le_msg = log_entry_msg(values) (timestamp, key, length, node_id, src, path) = tuple(values) # DEBUG print("TIMESTAMP = %d" % timestamp) print("KEY = %s" % key) print("LENGTH = %s" % length) # END # pylint: disable=no-member self.assertEqual(le_msg_spec.name, le_msg.name) # we don't have any nested enums or messages self.assertEqual(0, len(le_msg.enums)) self.assertEqual(0, len(le_msg.msgs)) # pylint: disable=no-member self.assertEqual(6, len(le_msg.fieldClasses)) self.assertEqual(6, len(le_msg)) # number of fields in instance for ndx, value in enumerate(le_msg): self.assertEqual(value, values[ndx]) # verify fields are accessible in the object ---------------- #(timestamp, key, length, nodeID, src, path) = tuple(values) self.assertEqual(timestamp, le_msg.timestamp) # pylint: disable=no-member self.assertEqual(key, le_msg.key) # pylint: disable=no-member self.assertEqual(length, le_msg.length) # pylint: disable=no-member self.assertEqual(node_id, le_msg.node_id) # pylint: disable=no-member self.assertEqual(src, le_msg.src) # pylint: disable=no-member self.assertEqual(path, le_msg.path) # serialize the object to the channel ----------------------- buf = chan.buffer chan.clear() nnn = le_msg.write_stand_alone(chan) self.assertEqual(5, nnn) # returns msg index old_position = chan.position # TESTING flip() chan.flip() self.assertEqual(old_position, chan.limit) # TESTING flip() self.assertEqual(0, chan.position) # TESTING flip() actual = chan.limit print("ACTUAL LENGTH OF SERIALIZED OBJECT: %u" % actual) # deserialize the channel, making a clone of the message ---- (readback, _) = MsgImpl.read(chan, self.s_obj_model) self.assertIsNotNone(readback) self.assertTrue(le_msg.__eq__(readback)) # produce another message from the same values -------------- le_msg2 = log_entry_msg(values) chan2 = Channel(BUFSIZE) nnn = le_msg2.write_stand_alone(chan2) chan2.flip() (copy2, nn3) = log_entry_msg.read(chan2, self.s_obj_model) self.assertTrue(le_msg.__eq__(readback)) self.assertTrue(le_msg2.__eq__(copy2)) self.assertEqual(nnn, nn3) # GEEP
def test_zone_mismatch_msg(self): # DEBUG print("\nTEST_ZONE_MISMATCH_MSG") # END # from setUp(): ============================================= # end stuff from setup ====================================== # ----------------------------------------------------------- # XXX This code has been crudely hacked from another test # module, and so needs careful review # ----------------------------------------------------------- # verify that this adds 1 (msg) + 3 (field count) to the number # of entries in getters, putters, etc self.assertIsNotNone(self.str_obj_model) self.assertTrue(isinstance(self.str_obj_model, M.ProtoSpec)) self.assertEqual('org.xlattice.alertz', self.str_obj_model.name) self.assertEqual(0, len(self.str_obj_model.enums)) self.assertEqual(16, len(self.str_obj_model.msgs)) self.assertEqual(0, len(self.str_obj_model.seqs)) msg_spec = self.str_obj_model.msgs[0] msg_name = msg_spec.name self.assertEqual('zoneMismatch', msg_name) # Create a channel ------------------------------------------ # its buffer will be used for both serializing # the instance # data and, by deserializing it, for creating a second instance. chan = Channel(BUFSIZE) buf = chan.buffer self.assertEqual(BUFSIZE, len(buf)) # create the ZoneMismatchMsg class ------------------------------ zone_mismatch_msg_cls = make_msg_class(self.str_obj_model, msg_name) # create a message instance --------------------------------- values = self.zone_mismatch_fields() # list of quasi-random values zmm_msg = zone_mismatch_msg_cls(values) self.assertEqual(msg_spec.name, zmm_msg._name) # we don't have any nested enums or messages self.assertEqual(0, len(zmm_msg.enums)) self.assertEqual(0, len(zmm_msg.msgs)) self.assertEqual(5, len(zmm_msg.field_classes)) self.assertEqual(5, len(zmm_msg)) # number of fields in instance self.assertEqual(values[0], zmm_msg.timestamp) self.assertEqual(values[1], zmm_msg.seq_nbr) self.assertEqual(values[2], zmm_msg.zone_name) self.assertEqual(values[3], zmm_msg.expected_serial) self.assertEqual(values[4], zmm_msg.actual_serial) # serialize the object to the channel ----------------------- # XXX WRITE HEADER FIRST! # DEBUG print("DIR (ZMM_MSG): ", end=' ') print(dir(zmm_msg)) # END zmm_msg.write_stand_alone(chan) chan.flip() # deserialize the channel, making a clone of the message ---- (read_back, nn2) = MsgImpl.read(chan, self.str_obj_model) self.assertIsNotNone(read_back) # DEBUG print("position after mis-match read back is %d" % chan.position) # END # verify that the messages are identical -------------------- self.assertTrue(zmm_msg.__eq__(read_back)) # produce another message from the same values -------------- zmm_msg2 = zone_mismatch_msg_cls(values) chan2 = Channel(BUFSIZE) zmm_msg2.write_stand_alone(chan2) chan2.flip() (copy2, nn3) = MsgImpl.read(chan2, self.str_obj_model) self.assertTrue(zmm_msg.__eq__(copy2)) self.assertTrue(zmm_msg2.__eq__(copy2)) # GEEP
def test_shutdown_msg(self): # DEBUG print("\nTEST_SHUTDOWN_MSG") # END # ----------------------------------------------------------- # XXX This code has been crudely hacked from another test # module, and so needs careful review # ----------------------------------------------------------- # verify that this adds 1 (msg) + 3 (field count) to the number # of entries in getters, writeStandAlones, etc msg_spec = self.str_obj_model.msgs[2] # <------ msg_name = msg_spec.name self.assertEqual('shutdown', msg_name) # Create a channel ------------------------------------------ # its buffer will be used for both serializing # the instance # data and, by deserializing it, for creating a second instance. chan = Channel(BUFSIZE) buf = chan.buffer self.assertEqual(BUFSIZE, len(buf)) # create the CorruptListMsg class ------------------------------ shutdown_msg_cls = make_msg_class(self.str_obj_model, msg_name) # create a message instance --------------------------------- values = [RNG.next_file_name(8), ] # list of quasi-random values sd_msg = shutdown_msg_cls(values) self.assertEqual(msg_name, sd_msg._name) # we don't have any nested enums or messages self.assertEqual(0, len(sd_msg.enums)) self.assertEqual(0, len(sd_msg.msgs)) self.assertEqual(1, len(sd_msg.field_classes)) # <--- self.assertEqual(1, len(sd_msg)) # number of fields in instance self.assertEqual(values[0], sd_msg.remarks) # serialize the object to the channel ----------------------- sd_msg.write_stand_alone(chan) chan.flip() # deserialize the channel, making a clone of the message ---- (read_back, nn5) = MsgImpl.read(chan, self.str_obj_model) self.assertIsNotNone(read_back) # DEBUG print("position after shutdown read back is %d" % chan.position) # END # verify that the messages are identical -------------------- self.assertTrue(sd_msg.__eq__(read_back)) # produce another message from the same values -------------- sd_msg2 = shutdown_msg_cls(values) chan2 = Channel(BUFSIZE) sd_msg2.write_stand_alone(chan2) chan2.flip() (copy2, nn6) = MsgImpl.read(chan2, self.str_obj_model) self.assertTrue(sd_msg.__eq__(copy2)) self.assertTrue(sd_msg2.__eq__(copy2)) # GEEP GEEP GEEP
def test_the_daemon(self): chan = Channel(BUFSIZE) chan.clear() # XXX should be guaranteed on new channel msg_count = 8 + RNG.next_int16(25) # so 8..32 # DEBUG print("MSG_COUNT = %u" % msg_count) # END # set up options ---------------------------------- now = int(time.time()) pgm_name_and_version = "testWithDummyClient v%s %s" % ( __version__, __version_date__) with open('/etc/hostname', 'r') as file: this_host = file.read().strip() options = {} # a namespace, so to speak options['ec2Host'] = False options['justShow'] = False options['log_dir'] = 'logs' options['pgm_name_and_version'] = pgm_name_and_version options['port'] = 55555 options['showTimestamp'] = False options['showVersion'] = False options['testing'] = True options['this_host'] = this_host options['timestamp'] = now options['verbose'] = False ns_ = Namespace(options) # clear the log files (so delete any files under logs/) ----- self.do_clear_logs(ns_) # start the daemon -------------------------------- daemon_t = threading.Thread(target=run_the_daemon, args=(ns_,)) daemon_t.start() # give the daemon time to wake up -------------------------- time.sleep(0.15) # XXX without this we get an abort saying # that libev cannot allocate (2G - 16)B # start sending (some fixed number of ) messages ------------ msgs_sent = [] for nnn in range(msg_count): msg = self.next_zone_mismatch_msg() seq_nbr_field = msg[1] # XXX by name would be better! self.assertEqual(nnn, seq_nbr_field.value) # serialize msg into the channel chan.clear() msg.write_stand_alone(chan) chan.flip() # send the msg to the daemon ------------------ skt = send_to_end_point(chan, '127.0.0.1', 55555) time.sleep(0.05) skt.close() msgs_sent.append(msg) # DEBUG print("MSG %d HAS BEEN SENT" % nnn) # END self.assertEqual(msg_count, len(msgs_sent)) # delay a few ms -------------------------------------------- time.sleep(0.05) # build and send shutdown msg ------------------------------- msg = self.next_shutdown_msg() chan.clear() msg.write_stand_alone(chan) chan.flip() skt = send_to_end_point(chan, '127.0.0.1', 55555) # DEBUG print("SHUTDOWN MSG HAS BEEN SENT") # END # delay a few ms -------------------------------------------- time.sleep(0.05) skt.close() # join the daemon thread ------------------------------------ time.sleep(0.05) daemon_t.join()