Example #1
0
    def test_cross_db_deadlock():

        fake_request(30.0)

        db1 = pmnc.state.get_database("db1")
        db2 = pmnc.state.get_queue("db2", re_len=6144)

        def f(txn):
            db1.put(b"key", b"value_1", txn)
            Timeout(3.0).wait()
            db2.append(pickle("item_1"), txn)

        def g(txn):
            db2.append(pickle("item_2"), txn)
            Timeout(3.0).wait()
            db1.put(b"key", b"value_2", txn)

        th_f = HeavyThread(target=lambda: pmnc.state.implicit_transaction(f))
        th_g = HeavyThread(target=lambda: pmnc.state.implicit_transaction(g))

        th_f.start()
        th_g.start()

        th_f.join()
        th_g.join()

        # now see what went through

        def fetch_result(txn):
            value = db1.get(b"key", None, txn)
            item1 = _pop(txn, db2, None, unpickle)
            item2 = _pop(txn, db2, None, unpickle)
            return value, item1, item2

        value, item1, item2 = pmnc.state.implicit_transaction(fetch_result)
        assert value in (b"value_1", b"value_2")
        assert (item1, item2) in (("item_1", "item_2"), ("item_2", "item_1"))
Example #2
0
    def test_cross_db_deadlock():

        fake_request(30.0)

        db1 = pmnc.state.get_database("db1")
        db2 = pmnc.state.get_queue("db2", re_len=6144)

        def f(txn):
            db1.put(b"key", b"value_1", txn)
            Timeout(3.0).wait()
            db2.append(pickle("item_1"), txn)

        def g(txn):
            db2.append(pickle("item_2"), txn)
            Timeout(3.0).wait()
            db1.put(b"key", b"value_2", txn)

        th_f = HeavyThread(target=lambda: pmnc.state.implicit_transaction(f))
        th_g = HeavyThread(target=lambda: pmnc.state.implicit_transaction(g))

        th_f.start()
        th_g.start()

        th_f.join()
        th_g.join()

        # now see what went through

        def fetch_result(txn):
            value = db1.get(b"key", None, txn)
            item1 = _pop(txn, db2, None, unpickle)
            item2 = _pop(txn, db2, None, unpickle)
            return value, item1, item2

        value, item1, item2 = pmnc.state.implicit_transaction(fetch_result)
        assert value in (b"value_1", b"value_2")
        assert (item1, item2) in (("item_1", "item_2"), ("item_2", "item_1"))
Example #3
0
def secondary_startup(node, cage, mode):

    cage_dir = os_path.join(cages_dir, cage)
    logs_dir = os_path.join(cage_dir, "logs")

    lib_dir = os_path.join(cage_dir, "lib")
    sys_path.insert(0, lib_dir)

    log_abbrevs = {
        1: "ERR",
        2: "MSG",
        3: "WRN",
        4: "LOG",
        5: "INF",
        6: "DBG",
        7: "NSE"
    }
    log_encoding = "windows-1251"
    log_translate = b"         \t                      " + bytes(range(
        32, 256))
    log_lock = Lock()

    log_yyyymmdd = None
    log_file = None

    # the following function will serve for all cage's logging

    def log(message, *, msg_level):

        nonlocal log_yyyymmdd, log_file

        line_time = time()
        line_yyyymmdd, line_hhmmss = strftime("%Y%m%d %H:%M:%S",
                                              localtime(line_time)).split(" ")
        log_line = "{0:s}.{1:02d} {2:s} [{3:s}] {4:s}".format(
            line_hhmmss,
            int(line_time * 100) % 100, log_abbrevs.get(msg_level, "???"),
            current_thread().name, message)
        with log_lock:

            if line_yyyymmdd != log_yyyymmdd:  # rotate log file
                try:
                    new_log_file_name = os_path.join(
                        logs_dir,
                        "{0:s}-{1:s}.log".format(cage, line_yyyymmdd))
                    new_log_file = fopen(
                        new_log_file_name,
                        os.O_WRONLY | os.O_CREAT | os.O_APPEND)
                except:
                    pass  # if rotation fails, previous log file will still be used
                else:
                    try:
                        close(log_file)
                    except:
                        pass  # this also catches the attempt to close None
                    log_file = new_log_file
                    log_yyyymmdd = line_yyyymmdd

            if log_file is not None:
                if message:
                    write(
                        log_file,
                        log_line.encode(log_encoding,
                                        "replace").translate(log_translate) +
                        b"\n")
                if msg_level == 1:
                    fsync(log_file)

    ###################################

    # create loader instance using initial default logging level

    pmnc = ModuleLoader(node, cage, cage_dir, log, "LOG", 2.0, 1.0)

    ###################################

    current_thread().name = "startup"

    if mode == "NORMAL":
        log("the cage is starting up", msg_level=2)
    elif mode == "FAILURE":
        log("the cage is restarting after a failure", msg_level=2)

    ###################################

    if win32_com:
        _main_thread_id = GetCurrentThreadId()

    def cage_thread_proc():
        try:
            pmnc.startup.start()
            try:
                while not pmnc.startup.wait(3.0):
                    pmnc.startup.maintenance()
            except:
                pmnc.log.error(exc_string())  # log and ignore
            finally:
                pmnc.startup.stop()
        finally:
            if win32_com:  # release the main thread blocked in PumpMessages
                PostThreadMessage(_main_thread_id, WM_QUIT)

    cage_thread = HeavyThread(target=cage_thread_proc, name="cage")
    cage_thread.start()

    ###################################

    def termination_watchdog_proc():
        try:
            while stdout.write("\n") > 0:
                stdout.flush()
                sleep(3.0)
        except:
            pass
        finally:
            pmnc.startup.exit()

    termination_watchdog = HeavyThread(target=termination_watchdog_proc,
                                       name="stdout")
    termination_watchdog.start()

    ###################################

    # wait for the cage thread to detect shutdown and terminate

    if win32_com:
        PumpMessages()  # in the meanwhile become a message pump

    cage_thread.join()

    ###################################

    log("the cage has been properly shut down", msg_level=2)
    log("", msg_level=1)  # force flush of a log file