Plan 9 from Bell Labs’s /usr/web/sources/contrib/mjl/wip/deluge/sched.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include "deluge.h"


void
strategy(Torrent *t)
{
	Peer *p;
	int new;

	if(bitnhave(t->haves) == t->npieces)
		new = Seeding;
	else if(bithaveall(t->reqpieces))
		new = Endgame;
	else if(bitnhave(t->haves) > 0)
		new = Rarestfirst;
	else
		new = Random;

	if(t->strategy == new)
		return;

	if(new == Seeding){
		if(t->dl != 0)
			trackrequest(t, "completed");
		DEBUG(2, "DOWNLOAD COMPLETED %R\n", t->rate);
	}

	if(new == Endgame){
		t->strategy = new;
		for(p = t->peers; p; p = p->next)
			if(!IsChoking(p))
				piecepeerschedule(t, p);
	}else{
		t->strategy = new;
	}
}


void
bitesrequested(Peer *p, Piece *pc, Bits *bits)
{
	Bite *b;

	bitclear(bits);
	for(b = p->lreq; b; b = b->next)
		if(b->piecen == pc->n)
			bitset(bits, b->n);
}

Piece *
nextpiece(Torrent *t, Peer *p)
{
	Piece *r, *n;
	int start;
	int i, index;
	Bits *bits;

	switch(t->strategy){
	case Random:
		assert(!bithaveall(t->reqpieces));
		start = rand() % t->npieces;
		for(i = 0; i < bitlen(t->reqpieces); i++){
			index = (start+i) % t->npieces;
			n = &t->pieces[index];
			if(!bitget(t->haves, index) && !bitget(t->reqpieces, index) && n->nids > 0)
				return n;
		}
		DEBUG(2, "nextpiece: no random piece to start on\n");
		return nil;
		break;

	case Rarestfirst:
		r = nil;
		for(i = 0; i < t->npieces; i++){
			n = &t->pieces[i];
			if(!bitget(t->haves, i) && !bitget(t->reqpieces, i) && n->nids > 0 && (r == nil || n->nids < r->nids)){
				r = n;
				if(r->nids == 1)
					break;
			}
		}
		return r;

	case Endgame:
		start = rand() % t->npieces;
		bits = bitnew((t->piecelen+Bitelength-1) / Bitelength, nil);
		for(i = 0; i < t->npieces; i++){
			index = (start+i) % t->npieces;
			if(bitget(t->haves, index))
				continue;

			bitesrequested(p, &t->pieces[index], bits);
			if(!bithaveall(bits)){
				bitfree(bits);
				return &t->pieces[index];
			}
		}
		bitfree(bits);
		return nil;

	case Seeding:
		DEBUG(2, "nextpiece: called when in state Seeding\n");
		return nil;

	default:
		sysfatal("nextpiece: cannot happen");
	}
	return nil;
}

Bite *
piecenextbite(Torrent *t, Peer *p, Piece *pc)
{
	int i;
	int bitelen;
	Bits *bits;

	if(bithaveall(pc->bites))
		return nil;

	switch(t->strategy){
	case Random:
	case Rarestfirst:
		if(bitnhave(pc->bites) + bitnhave(pc->reqbites) >= bitlen(pc->reqbites))
			return nil;
		for(i = 0; i < bitlen(pc->reqbites); i++){
			if(!bitget(pc->bites, i) && !bitget(pc->reqbites, i)){
				bitelen = MIN(Bitelength, t->length - pc->n * t->piecelen - i*Bitelength);
				return bitenew(i, pc->n, i*Bitelength, bitelen);
			}
		}
		sysfatal("piecenextbite: cannot happen, no bite in piece after all (rarest/random)");

	case Endgame:
		bits = bitnew(bitlen(pc->reqbites), nil);
		bitesrequested(p, pc, bits);
		if(bitnhave(pc->bites) + bitnhave(bits) >= bitlen(bits)){
			bitfree(bits);
			return nil;
		}
		for(i = 0; i < bitlen(bits); i++){
			if(!bitget(pc->bites, i) && !bitget(bits, i)){
				bitfree(bits);
				bitelen = MIN(Bitelength, t->length - pc->n * t->piecelen - i*Bitelength);
				return bitenew(i, pc->n, i*Bitelength, bitelen);
			}
		}
		sysfatal("piecenextbite: cannot happen, no bite in piece after all (endgame)");

	case Seeding:
		DEBUG(2, "piecenextbite: next bite requested for strategy Seeding\n");
		return nil;

	default:
		sysfatal("piecenextbite: cannot happen");
	}
	return nil;
}

Bite *
nextbite(Torrent *t, Peer *p)
{
	Bite *b, *rb;
	Piece *pc;

	for(b = p->lreq; b; b = b->next){
		pc = &t->pieces[b->piecen];
		rb = piecenextbite(t, p, pc);
		if(rb)
			return rb;
	}
	pc = nextpiece(t, p);
	if(pc){
		return piecenextbite(t, p, pc);
	}
	DEBUG(2, "nextbite: no new pieces to start on\n");
	return nil;
}

void
piecepeerschedule(Torrent *t, Peer *p)
{
	Bite *b;

	strategy(t);
	while(bitelen(p->lreq) < Minscheduled){
		b = nextbite(t, p);
		if(b == nil){
			DEBUG(2, "no more bites  to schedule\n");
			return;
		}

		request(t, p, b);
		strategy(t);
	}
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.