NodeID pickNextNodeToQuery(bool& out_at_least_one_request_needed) const
    {
        out_at_least_one_request_needed = false;

        for (unsigned iter_cnt_ = 0; iter_cnt_ < (sizeof(entries_) / sizeof(entries_[0])); iter_cnt_++) // Round-robin
        {
            last_picked_node_++;
            if (last_picked_node_ > NodeID::Max)
            {
                last_picked_node_ = 1;
            }
            UAVCAN_ASSERT((last_picked_node_ >= 1) &&
                          (last_picked_node_ <= NodeID::Max));

            const Entry& entry = getEntry(last_picked_node_);

            if (entry.request_needed)
            {
                out_at_least_one_request_needed = true;

                if (entry.updated_since_last_attempt &&
                    !get_node_info_client_.hasPendingCallToServer(last_picked_node_))
                {
                    UAVCAN_TRACE("NodeInfoRetriever", "Next node to query: %d", int(last_picked_node_));
                    return NodeID(last_picked_node_);
                }
            }
        }

        return NodeID();        // No node could be found
    }
    void constrain_to_field(Node& n1) {

        // keep snake in the middle of the left area
        if (n1.type() == COMMIT || n1.display_type() == SNAKE_TAIL || n1.display_type() == HEAD) {
            n1.velocity().x -= 0.0001*pow(n1.pos().x-graph.left_border/2,3);
        }

        // keep HEAD around y = graph.history_pos
        if (n1.oid() == NodeID(REF, "HEAD"))
            n1.velocity().y -= 0.0001*pow(n1.pos().y-graph.history_pos,3);

        float border = 200;
        float strength = 0.00002;

        // keep blobs and trees in the middle area
        if (n1.type() == BLOB || n1.type() == TREE) {
            if (n1.pos().x < graph.left_border + border)
                n1.velocity().x += strength*pow(graph.left_border + border - n1.pos().x,3);
            if (n1.pos().x > graph.right_border - border)
                n1.velocity().x += strength*pow(graph.right_border - border - n1.pos().x,3);
            if (n1.pos().y < border)
                n1.velocity().y += strength*pow(border - n1.pos().y,3);
            if (n1.pos().y > graph.height-border)
                n1.velocity().y += strength*pow(graph.height - border - n1.pos().y,3);
        }
    }
Example #3
0
void ProofNode::PrintNodes(ostream& fout)
{
    //print child connections if possible
    if (_left)
    {
        fout << "\t"+NodeID()+" -> "+_left->NodeID()+" ;" << endl;
    }

    if (_right)
    {
        fout << "\t"+NodeID()+" -> "+_right->NodeID()+" ;" << endl;
    }

    //recurse to lower nodes
    if (_left) this->_left->PrintNodes(fout);
    if (_right) this->_right->PrintNodes(fout);
}
Example #4
0
// Internally uses DFS for graph traversal (in fact it's topological sort)
void NodeTree::prepareListImpl()
{
    // Initialize color map with white color
    std::vector<ENodeColor> colorMap(_nodes.size(), ENodeColor::White);

    _executeList.clear();

    // For each invalid nodes (in terms of executable) mark them black
    // so "true" graph traversal can skip them
    for(NodeID nodeID = 0; nodeID < NodeID(_nodes.size()); ++nodeID)
    {
        if(!validateNode(nodeID))
            continue;

        if(colorMap[nodeID] != ENodeColor::White)
            continue;

        if(isNodeExecutable(nodeID))
            continue;

        if(!depthFirstSearch(nodeID, colorMap))
            return;
    }	

    // For each tagged and valid nodes that haven't been visited yet do ..
    for(NodeID nodeID = 0; nodeID < NodeID(_nodes.size()); ++nodeID)
    {
        if(!validateNode(nodeID))
            continue;

        if(colorMap[nodeID] != ENodeColor::White)
            continue;

        if(!_nodes[nodeID].flag(ENodeFlags::Tagged))
            continue;

        if(!depthFirstSearch(nodeID, colorMap, &_executeList))
        {
            _executeList.clear();
            return;
        }
    }

    // Topological sort gives result in inverse order
    std::reverse(std::begin(_executeList), std::end(_executeList));
}
Example #5
0
void ObjectCM::_sendEmptyVersion( const MasterCMCommand& command,
                                  const uint128_t& version,
                                  const bool multicast )
{
    NodePtr node = command.getNode();
    ConnectionPtr connection = node->getConnection( multicast );

    ObjectDataOCommand( Connections( 1, connection ), CMD_OBJECT_INSTANCE,
                        COMMANDTYPE_OBJECT, _object->getID(),
                        command.getInstanceID(), version, 0, 0, true, 0 )
            << NodeID() << _object->getInstanceID();
}
Example #6
0
void NodeTree::notifyFinish()
{
    for(NodeID nodeID = 0; nodeID < NodeID(_nodes.size()); ++nodeID)
    {
        if(!validateNode(nodeID))
            continue;

        _nodes[nodeID].finish();

        // Finally, tag node that need to be auto-tagged
        if(_nodes[nodeID].flag(ENodeFlags::AutoTag))
            tagNode(nodeID);
    }
}
Example #7
0
 Node &nearest_node(float x, float y) {
     Node *best = 0;
     float best_distance = 99999999;
     Vec2f pos(x,y);
     for(map<NodeID,Node>::iterator it = nodes.begin(); it != nodes.end(); it++) {
         if (!it->second.visible()) continue;
         if (it->second.oid() == NodeID(INDEX,"index")) continue;
         if (it->second.oid().type == INDEX_ENTRY) continue;
         float distance = it->second.pos().distance(pos);
         if (distance < best_distance) {
             best_distance = distance;
             best = &(it->second);
         }
     }
     return (*best);
 }
 NodeID pickNextNodeToQueryAndCleanupMap()
 {
     NodeID node_id;
     do
     {
         node_id = pickNextNodeToQuery();
         if (node_id.isUnicast())
         {
             if (needToQuery(node_id))
             {
                 return node_id;
             }
             else
             {
                 removeNode(node_id);
             }
         }
     }
     while (node_id.isUnicast());
     return NodeID();
 }
Example #9
0
NodeID NodeTree::allocateNodeID()
{
    NodeID id = InvalidNodeID;

    // Check for recycled ids
    if(_recycledIDs.empty())
    {
        // Need to create new one
        id = NodeID(_nodes.size());
        // Expand node array - createNode relies on it
        _nodes.resize(_nodes.size() + 1); 
    }
    else
    {
        // Reuse unused but still cached one
        id = _recycledIDs.back();
        _recycledIDs.pop_back();
    }

    return id;
}
Example #10
0
//---------------------------------------------------------------------------
// identifier master node mapping
//---------------------------------------------------------------------------
NodeID ObjectStore::findMasterNodeID( const uint128_t& identifier )
{
    LB_TS_NOT_THREAD( _commandThread );

    // OPT: look up locally first?
    Nodes nodes;
    _localNode->getNodes( nodes );

    // OPT: send to multiple nodes at once?
    for( NodesIter i = nodes.begin(); i != nodes.end(); ++i )
    {
        NodePtr node = *i;
        lunchbox::Request< NodeID > request =
            _localNode->registerRequest< NodeID >();

        LBLOG( LOG_OBJECTS ) << "Finding " << identifier << " on " << node
                             << " req " << request.getID() << std::endl;
        node->send( CMD_NODE_FIND_MASTER_NODE_ID ) << identifier << request;

        try
        {
            const NodeID& masterNodeID = request.wait( Global::getTimeout( ));

            if( masterNodeID != 0 )
            {
                LBLOG( LOG_OBJECTS ) << "Found " << identifier << " on "
                                     << masterNodeID << std::endl;
                return masterNodeID;
            }
        }
        catch( const lunchbox::FutureTimeout& )
        {
            _localNode->unregisterRequest( request.getID( ));
            throw;
        }
    }

    return NodeID();
}
Example #11
0
 NodeID pickNextNodeToQuery() const
 {
     // This essentially means that we pick first available node. Remember that the map is unordered.
     const NodeMap::KVPair* const pair = node_map_.getByIndex(0);
     return (pair == NULL) ? NodeID() : pair->key;
 }
Example #12
0
void ProofNode::PrintLabels(ostream& fout)
{
    fout << NodeID() << " [label=" << NodeName() << "];" << endl;
    if (_left) this->_left->PrintLabels(fout);
    if (_right) this->_right->PrintLabels(fout);
}
Example #13
0
    /**
     * Initialization is performed as follows (every step may fail and return an error):
     *  1. Log is restored or initialized.
     *  2. Current term is restored. If there was no current term stored and the log is empty, it will be initialized
     *     with zero.
     *  3. VotedFor value is restored. If there was no VotedFor value stored, the log is empty, and the current term is
     *     zero, the value will be initialized with zero.
     */
    int init()
    {
        /*
         * Reading log
         */
        int res = log_.init();
        if (res < 0)
        {
            UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState", "Log init failed: %d", res);
            return res;
        }

        const Entry* const last_entry = log_.getEntryAtIndex(log_.getLastIndex());
        if (last_entry == UAVCAN_NULLPTR)
        {
            UAVCAN_ASSERT(0);
            return -ErrLogic;
        }

        const bool log_is_empty = (log_.getLastIndex() == 0) && (last_entry->term == 0);

        StorageMarshaller io(storage_);

        /*
         * Reading currentTerm
         */
        if (storage_.get(getCurrentTermKey()).empty() && log_is_empty)
        {
            // First initialization
            current_term_ = 0;
            res = io.setAndGetBack(getCurrentTermKey(), current_term_);
            if (res < 0)
            {
                UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
                             "Failed to init current term: %d", res);
                return res;
            }
            if (current_term_ != 0)
            {
                return -ErrFailure;
            }
        }
        else
        {
            // Restoring
            res = io.get(getCurrentTermKey(), current_term_);
            if (res < 0)
            {
                UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
                             "Failed to read current term: %d", res);
                return res;
            }
        }

        tracer_.onEvent(TraceRaftCurrentTermRestored, current_term_);

        if (current_term_ < last_entry->term)
        {
            UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
                         "Persistent storage is damaged: current term is less than term of the last log entry (%u < %u)",
                         unsigned(current_term_), unsigned(last_entry->term));
            return -ErrLogic;
        }

        /*
         * Reading votedFor
         */
        if (storage_.get(getVotedForKey()).empty() && log_is_empty && (current_term_ == 0))
        {
            // First initialization
            voted_for_ = NodeID(0);
            uint32_t stored_voted_for = 0;
            res = io.setAndGetBack(getVotedForKey(), stored_voted_for);
            if (res < 0)
            {
                UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
                             "Failed to init votedFor: %d", res);
                return res;
            }
            if (stored_voted_for != 0)
            {
                return -ErrFailure;
            }
        }
        else
        {
            // Restoring
            uint32_t stored_voted_for = 0;
            res = io.get(getVotedForKey(), stored_voted_for);
            if (res < 0)
            {
                UAVCAN_TRACE("dynamic_node_id_server::distributed::PersistentState",
                             "Failed to read votedFor: %d", res);
                return res;
            }
            if (stored_voted_for > NodeID::Max)
            {
                return -ErrInvalidConfiguration;
            }
            voted_for_ = NodeID(uint8_t(stored_voted_for));
        }

        tracer_.onEvent(TraceRaftVotedForRestored, voted_for_.get());

        return 0;
    }
Example #14
0
 int resetVotedFor() { return setVotedFor(NodeID(0)); }
int DynamicNodeIDClient::start(const protocol::HardwareVersion& hardware_version,
                               const NodeID preferred_node_id,
                               const TransferPriority transfer_priority)
{
    terminate();

    // Allocation is not possible if node ID is already set
    if (dnida_pub_.getNode().getNodeID().isUnicast())
    {
        return -ErrLogic;
    }

    // Unique ID initialization & validation
    copy(hardware_version.unique_id.begin(), hardware_version.unique_id.end(), unique_id_);
    bool unique_id_is_zero = true;
    for (uint8_t i = 0; i < sizeof(unique_id_); i++)
    {
        if (unique_id_[i] != 0)
        {
            unique_id_is_zero = false;
            break;
        }
    }

    if (unique_id_is_zero)
    {
        return -ErrInvalidParam;
    }

    if (!preferred_node_id.isValid())  // Only broadcast and unicast are allowed
    {
        return -ErrInvalidParam;
    }

    // Initializing the fields
    preferred_node_id_ = preferred_node_id;
    allocated_node_id_ = NodeID();
    allocator_node_id_ = NodeID();
    UAVCAN_ASSERT(preferred_node_id_.isValid());
    UAVCAN_ASSERT(!allocated_node_id_.isValid());
    UAVCAN_ASSERT(!allocator_node_id_.isValid());

    // Initializing node objects - Rule A
    int res = dnida_pub_.init();
    if (res < 0)
    {
        return res;
    }
    dnida_pub_.allowAnonymousTransfers();
    dnida_pub_.setPriority(transfer_priority);

    res = dnida_sub_.start(AllocationCallback(this, &DynamicNodeIDClient::handleAllocation));
    if (res < 0)
    {
        return res;
    }
    dnida_sub_.allowAnonymousTransfers();

    startPeriodic(MonotonicDuration::fromMSec(protocol::dynamic_node_id::Allocation::DEFAULT_REQUEST_PERIOD_MS));

    return 0;
}