Exemplo n.º 1
0
/* Split a bucket into two equal parts. */
bool
RoutingTable::split(const RoutingTable::iterator& b)
{
    InfoHash new_id;
    try {
        new_id = middle(b);
    } catch (const std::out_of_range& e) {
        return false;
    }

    // Insert new bucket
    insert(std::next(b), Bucket {b->af, new_id, b->time});

    // Re-assign nodes
    std::list<Sp<Node>> nodes {};
    nodes.splice(nodes.begin(), b->nodes);
    while (!nodes.empty()) {
        auto n = nodes.begin();
        auto b = findBucket((*n)->id);
        if (b == end())
            nodes.erase(n);
        else
            b->nodes.splice(b->nodes.begin(), nodes, n);
    }
    return true;
}
Exemplo n.º 2
0
bool
RoutingTable::onNewNode(const Sp<Node>& node, int confirm, const time_point& now, const InfoHash& myid, net::NetworkEngine& ne) {
    auto b = findBucket(node->id);
    if (b == end()) return false;

    if (confirm == 2)
        b->time = now;

    for (auto& n : b->nodes) {
        if (n == node)
            return false;
    }

    bool mybucket = contains(b, myid);
    if (mybucket) {
        grow_time = now;
        //scheduler.edit(nextNodesConfirmation, now);
    }

    if (b->nodes.size() >= TARGET_NODES) {
        /* Try to get rid of an expired node. */
        for (auto& n : b->nodes)
            if (n->isExpired()) {
                n = node;
                return true;
            }
        /* Bucket full.  Ping a dubious node */
        bool dubious = false;
        for (auto& n : b->nodes) {
            /* Pick the first dubious node that we haven't pinged in the
               last 9 seconds.  This gives nodes the time to reply, but
               tends to concentrate on the same nodes, so that we get rid
               of bad nodes fast. */
            if (not n->isGood(now)) {
                dubious = true;
                if (not n->isPendingMessage()) {
                    //DHT_LOG.d(n->id, "[node %s] sending ping to dubious node", n->toString().c_str());
                    ne.sendPing(n, nullptr, nullptr);
                    break;
                }
            }
        }

        if ((mybucket || (is_client and depth(b) < 6)) && (!dubious || size() == 1)) {
            //DHT_LOG.d("Splitting from depth %u", depth(b));
            b->sendCachedPing(ne);
            split(b);
            return onNewNode(node, confirm, now, myid, ne);
        }

        /* No space for this node.  Cache it away for later. */
        if (confirm or not b->cached)
            b->cached = node;
    } else {
        /* Create a new node. */
        b->nodes.emplace_front(node);
    }
    return true;
}
Exemplo n.º 3
0
    bool exists(const int p, const prevPlanes &pp) const {
        if (p>0 && (pp[0] < min0 || pp[0] > ranges->max(0))) return false;
        if (p>1 && (pp[1] < min1 || pp[1] > ranges->max(1))) return false;

        ColorVal rmin, rmax;
        ColorVal v=pp[p];
        ranges->snap(p,pp,rmin,rmax,v);
        if (v != pp[p]) return false;   // bucket empty because of original range constraints

        const ColorBucket b = findBucket(p,pp);
        //if (b.min > b.max) return false;
        if (b.snapColor_slow(pp[p]) != pp[p]) return false;
        return true;
    }
Exemplo n.º 4
0
void NodeTree::removeNode( NodeSPtr address )
{
    if (!address.get())
        throw std::invalid_argument("Node is not set");

    std::lock_guard<std::mutex> lock(mutex);

    BucketContainer::const_iterator bucket_it = findBucket(*address);

    BucketContainer::key_type bucket = *bucket_it;
    assert(bucket->inBounds(address));

    bucket->remove(*address);
}
Exemplo n.º 5
0
/** Updates the value in a certain date range.<br>
  * This will create a new bucket if required. */
DECLARE_EXPORT void Calendar::setValue(Date start, Date end, const double v)
{
  CalendarBucket* x = static_cast<CalendarBucket*>(findBucket(start));
  if (x && x->getStart() == start && x->getEnd() <= end)
    // We can update an existing bucket: it has the same start date
    // and ends before the new effective period ends.
    x->setEnd(end);
  else
  {
    // Creating a new bucket
    x = new CalendarBucket();
    x->setStart(start);
    x->setEnd(end);
    x->setCalendar(this);
  }
  x->setValue(v);
  x->setPriority(lowestPriority()-1);
}
Exemplo n.º 6
0
// This method will not return the exact 8 closest, but fetches the nodes from
// three buckets, the right one and the 2 adjacent ones.
// In case we have a lot of nodes it will be precise, if not then we can't 
// expect to have a precise result anyway.
const std::list<NodeSPtr> NodeTree::getClosestNodes(
    const NodeData& data) const
{
    std::list<NodeSPtr> nodes;
    std::lock_guard<std::mutex> lock(mutex);
    
    std::set<NodeSPtr,std::function<bool(const NodeSPtr&,const NodeSPtr&)> > knownNodes(
        [&data]( const NodeSPtr& x, const NodeSPtr& y) {
            return (*x ^ data) <= (*y ^ data);
        });

    // find bucket
    auto bucket_it = findBucket(data);
    
    // check if we have a perfect match
    const Bucket::const_iterator perfect_match = std::find_if(
        (*bucket_it)->cbegin(),(*bucket_it)->cend(),
            [&data](const NodeSPtr& a) { return *a == data; } );
    
    if ( perfect_match != (*bucket_it)->cend() )
    {
        nodes.push_back(*perfect_match);
        return nodes;
    }
    
    // in case a perfect match is not found the closest nodes are returned
    if (bucket_it != _buckets.begin())
        --bucket_it; // put it at the left bucket

    for( int i = 0; i < 3 && bucket_it != _buckets.end(); ++i, ++bucket_it )
    {
        for( auto it = (*bucket_it)->cbegin(); it != (*bucket_it)->cend(); ++it)
        {
            knownNodes.insert(*it);
        }
    }

    auto it = knownNodes.begin();
    for( size_t __i = 0; __i < knownNodes.size() && __i < DHT_FIND_NODE_COUNT;  ++__i, ++it )
    {
        nodes.push_back(*it);
    }
    return nodes;
}
Exemplo n.º 7
0
std::vector<Sp<Node>>
RoutingTable::findClosestNodes(const InfoHash id, time_point now, size_t count) const
{
    std::vector<Sp<Node>> nodes;
    nodes.reserve(count);
    auto bucket = findBucket(id);

    if (bucket == end()) { return nodes; }

    auto sortedBucketInsert = [&](const Bucket &b) {
        for (auto n : b.nodes) {
            if (not n->isGood(now))
                continue;

            auto here = std::find_if(nodes.begin(), nodes.end(),
                [&id,&n](Sp<Node> &node) {
                    return id.xorCmp(n->id, node->id) < 0;
                }
            );
            nodes.insert(here, n);
        }
    };

    auto itn = bucket;
    auto itp = (bucket == begin()) ? end() : std::prev(bucket);
    while (nodes.size() < count && (itn != end() || itp != end())) {
        if (itn != end()) {
            sortedBucketInsert(*itn);
            itn = std::next(itn);
        }
        if (itp != end()) {
            sortedBucketInsert(*itp);
            itp = (itp == begin()) ? end() : std::prev(itp);
        }
    }

    // shrink to the count closest nodes.
    if (nodes.size() > count) {
        nodes.resize(count);
    }
    return nodes;
}
Exemplo n.º 8
0
bool NodeTree::addNode( NodeSPtr address )
{
    if (!address.get())
        throw std::invalid_argument("Node is not set");

    std::lock_guard<std::mutex> lock(mutex);

    BucketContainer::const_iterator bucket_it = findBucket(*address);
    assert(bucket_it != _buckets.end());

    BucketContainer::key_type bucket = *bucket_it;
    assert(bucket->inBounds(address));

    bool isAdded = bucket->add(address);
    if ( !isAdded && bucket->inBounds(_node) )
    {
        MaybeBuckets maybe_split_buckets = split(bucket_it);

        // unsplittable, ignore it
        if (!maybe_split_buckets)
            return false;

        BucketSPtrPair& split_buckets = *maybe_split_buckets;

        assert(split_buckets.first->inBounds(address) ||
               split_buckets.second->inBounds(address));

        if (split_buckets.first->inBounds(address))
        {
            isAdded = split_buckets.first->add(address);
        }
        else
        {
            assert(split_buckets.second->inBounds(address));
            isAdded = split_buckets.second->add(address);
        }
        return isAdded;
    }

    return isAdded;
}
Exemplo n.º 9
0
 void addColor(const std::vector<ColorVal> &pixel) {
     for (unsigned int p=0; p < pixel.size(); p++) {
             findBucket(p, pixel).addColor(pixel[p],max_per_colorbucket[p]);
     }
 }
Exemplo n.º 10
0
const boost::optional<NodeSPtr> NodeTree::getNode(
    const NodeData& data ) const noexcept
{
    return (*findBucket(data))->find(data); 
}