示例#1
0
文件: replica.cpp 项目: SunnyGyb/rDSN
void replica::close()
{
    if (status() != PS_INACTIVE && status() != PS_ERROR)
    {
        update_local_configuration_with_no_ballot_change(PS_INACTIVE);
    }

    cleanup_preparing_mutations(true);
    _primary_states.cleanup();
    _potential_secondary_states.cleanup(true);

    if (_app != nullptr)
    {
        _app->close(false);
    }
}
示例#2
0
文件: replica.cpp 项目: ykwd/rDSN
void replica::close()
{
    dassert(
        status() == partition_status::PS_ERROR || status() == partition_status::PS_INACTIVE,
        "%s: invalid state %s when calling replica::close",
        name(),
        enum_to_string(status())
        );

    if (nullptr != _checkpoint_timer)
    {
        _checkpoint_timer->cancel(true);
        _checkpoint_timer = nullptr;
    }

    cleanup_preparing_mutations(true);
    dassert(_primary_states.is_cleaned(), "primary context is not cleared");

    if (partition_status::PS_INACTIVE == status())
    {
        dassert(_secondary_states.is_cleaned(), "secondary context is not cleared");
        dassert(_potential_secondary_states.is_cleaned(), "potential secondary context is not cleared");
    }

    // for partition_status::PS_ERROR, context cleanup is done here as they may block
    else
    {
        bool r = _secondary_states.cleanup(true);
        dassert(r, "secondary context is not cleared");
        
        r = _potential_secondary_states.cleanup(true);
        dassert(r, "potential secondary context is not cleared");
    }
    
    if (_private_log != nullptr)
    {
        _private_log->close();
        _private_log = nullptr;
    }

    if (_app != nullptr)
    {
        _app->close(false);
    }
}
示例#3
0
bool replica::update_local_configuration(const replica_configuration& config, bool same_ballot/* = false*/)
{
    dassert(config.ballot > get_ballot()
        || (same_ballot && config.ballot == get_ballot()), "");
    dassert (config.gpid == get_gpid(), "");

    partition_status old_status = status();
    ballot old_ballot = get_ballot();

    // skip unncessary configuration change
    if (old_status == config.status && old_ballot == config.ballot)
        return true;

    // skip invalid change
    switch (old_status)
    {
    case PS_ERROR:
        {
            ddebug(
                "%s: status change from %s @ %lld to %s @ %lld is not allowed",
                name(),
                enum_to_string(old_status),
                old_ballot,
                enum_to_string(config.status),
                config.ballot
                );
            return false;
        }
        break;
    case PS_INACTIVE:
        if ((config.status == PS_PRIMARY || config.status == PS_SECONDARY)
            && !_inactive_is_transient)
        {
            ddebug(
                "%s: status change from %s @ %lld to %s @ %lld is not allowed when inactive state is not transient",
                name(),
                enum_to_string(old_status),
                old_ballot,
                enum_to_string(config.status),
                config.ballot
                );
            return false;
        }
        break;
    case PS_POTENTIAL_SECONDARY:
        if (config.status == PS_ERROR || config.status == PS_INACTIVE)
        {
            if (!_potential_secondary_states.cleanup(false))
            {
                dwarn(
                    "%s: status change from %s @ %lld to %s @ %lld is not allowed coz learning remote state is still running",
                    name(),
                    enum_to_string(old_status),
                    old_ballot,
                    enum_to_string(config.status),
                    config.ballot
                    );
                return false;
            }
        }
        break;
    case PS_SECONDARY:
        if (config.status != PS_SECONDARY
            && _secondary_states.checkpoint_task != nullptr)
        {
            dwarn(
                "%s: status change from %s @ %lld to %s @ %lld is not allowed coz checkpointing is still running",
                name(),
                enum_to_string(old_status),
                old_ballot,
                enum_to_string(config.status),
                config.ballot
                );
            return false;
        }
        break;
    }

    uint64_t oldTs = _last_config_change_time_ms;
    _config = config;
    _last_config_change_time_ms =now_ms();
    dassert (max_prepared_decree() >= last_committed_decree(), "");
    
    switch (old_status)
    {
    case PS_PRIMARY:
        cleanup_preparing_mutations(true);
        switch (config.status)
        {
        case PS_PRIMARY:
            replay_prepare_list();
            break;
        case PS_INACTIVE:
            _primary_states.cleanup(old_ballot != config.ballot);
            break;
        case PS_SECONDARY:
        case PS_ERROR:
            _primary_states.cleanup();
            break;
        case PS_POTENTIAL_SECONDARY:
            dassert (false, "invalid execution path");
            break;
        default:
            dassert (false, "invalid execution path");
        }        
        break;
    case PS_SECONDARY:
        cleanup_preparing_mutations(true);
        switch (config.status)
        {
        case PS_PRIMARY:
            init_group_check();            
            replay_prepare_list();
            break;
        case PS_SECONDARY:
            break;
        case PS_POTENTIAL_SECONDARY:
            // InActive in config
            break;
        case PS_INACTIVE:
            break;
        case PS_ERROR:
            break;
        default:
            dassert (false, "invalid execution path");
        }
        break;
    case PS_POTENTIAL_SECONDARY:
        switch (config.status)
        {
        case PS_PRIMARY:
            dassert (false, "invalid execution path");
            break;
        case PS_SECONDARY:
            _prepare_list->truncate(_app->last_committed_decree());            
            _potential_secondary_states.cleanup(true);
            check_state_completeness();
            break;
        case PS_POTENTIAL_SECONDARY:
            break;
        case PS_INACTIVE:
            _potential_secondary_states.cleanup(true);
            break;
        case PS_ERROR:
            _prepare_list->reset(_app->last_committed_decree());
            _potential_secondary_states.cleanup(true);
            break;
        default:
            dassert (false, "invalid execution path");
        }
        break;
    case PS_INACTIVE:        
        switch (config.status)
        {
        case PS_PRIMARY:
            _inactive_is_transient = false;
            init_group_check();
            replay_prepare_list();
            break;
        case PS_SECONDARY:            
            _inactive_is_transient = false;
            break;
        case PS_POTENTIAL_SECONDARY:
            _inactive_is_transient = false;
            break;
        case PS_INACTIVE:
            break;
        case PS_ERROR:
            _inactive_is_transient = false;
            break;
        default:
            dassert (false, "invalid execution path");
        }
        break;
    case PS_ERROR:
        switch (config.status)
        {
        case PS_PRIMARY:
            dassert (false, "invalid execution path");
            break;
        case PS_SECONDARY:
            dassert (false, "invalid execution path");
            break;
        case PS_POTENTIAL_SECONDARY:
            dassert(false, "invalid execution path");
            break;
        case PS_INACTIVE:
            dassert (false, "invalid execution path");
            break;
        case PS_ERROR:
            break;
        default:
            dassert (false, "invalid execution path");
        }
        break;
    default:
        dassert (false, "invalid execution path");
    }

    dwarn(
        "%s: status change %s @ %lld => %s @ %lld, pre(%llu, %llu), app(%llu, %llu), duration=%llu ms",
        name(),
        enum_to_string(old_status),
        old_ballot,
        enum_to_string(status()),
        get_ballot(),
        _prepare_list->max_decree(),
        _prepare_list->last_committed_decree(),
        _app->last_committed_decree(),
        _app->last_durable_decree(),
        _last_config_change_time_ms - oldTs
        );

    if (status() != old_status)
    {
        bool isClosing = (status() == PS_ERROR || (status() == PS_INACTIVE && get_ballot() > old_ballot));
        _stub->notify_replica_state_update(config, isClosing);

        if (isClosing)
        {
            ddebug("%s: being close ...", name());
            _stub->begin_close_replica(this);
            return false;
        }
    }
    else
    {
        _stub->notify_replica_state_update(config, false);
    }
    return true;
}