Example #1
0
func NewPieceData(bitfield *bit_field.Bitfield, pieceLength, lastPieceLength int64) (p *PieceData) {
	p = new(PieceData)
	p.pieces = make(map[int64]*Piece, bitfield.Len())
	p.peers = make(map[string]map[uint64]int64, ACTIVE_PEERS+INCOMING_PEERS)
	p.bitfield = bitfield
	p.pieceLength = pieceLength
	p.lastPieceLength = lastPieceLength
	return
}
Example #2
0
func (pd *PieceData) SearchPiece(addr string, bitfield *bit_field.Bitfield) (rpiece int64, rblock int, err os.Error) {
	// Check if peer has some of the active pieces to finish them
	//log.Println("PieceData -> Searching for an already present piece")
	for k, piece := range pd.pieces {
		available := -1
		for block, downloads := range piece.downloaderCount {
			if downloads == 0 {
				available = block
				break
			}
		}
		if available != -1 && bitfield.IsSet(k) {
			// Send request piece k, block available
			pd.Add(addr, k, available)
			rpiece, rblock = k, available
			return
		}
	}
	//log.Println("PieceData -> No suitable piece found in active set")
	// Check what piece we can request
	totalPieces := pd.bitfield.Len()
	bytes := bitfield.Bytes()
	start := rand.Int63n(totalPieces)
	// Search fordward
	//log.Println("PieceData -> Searching fordwards")
	for piece := pd.bitfield.FindNextPiece(start, bytes); piece != -1 && piece < totalPieces; piece = pd.bitfield.FindNextPiece(piece+1, bytes) {
		//log.Println("PieceData -> Piece found, see if it's already in active piece set:", piece)
		if _, ok := pd.pieces[piece]; !ok {
			// Add new piece to set
			pd.Add(addr, piece, 0)
			rpiece, rblock = piece, 0
			return
		}
	}
	// Search backwards
	//log.Println("PieceData -> Searching backwards")
	for piece := pd.bitfield.FindNextPiece(0, bytes); piece != -1 && piece < start; piece = pd.bitfield.FindNextPiece(piece+1, bytes) {
		//log.Println("PieceData -> Piece found, see if it's already in active piece set:", piece)
		if _, ok := pd.pieces[piece]; !ok {
			// Add new piece to set
			pd.Add(addr, piece, 0)
			rpiece, rblock = piece, 0
			return
		}
	}
	// If all pieces are taken, double up on an active piece
	// if only 20% of pieces remaining
	//log.Println("PieceData -> Trying to enter endgame mode")
	if float64(pd.bitfield.Count())/float64(pd.bitfield.Len()) < 0.80 {
		err = os.NewError("No available block found")
		return
	}
	//log.Println("PieceData -> Doubling up on an active piece")
	first := true
	min := 0
	for k, piece := range pd.pieces {
		for block, downloads := range piece.downloaderCount {
			if bitfield.IsSet(k) && !pd.CheckRequested(addr, k, block) {
				if first && downloads != -1 {
					rpiece, rblock, min = k, block, downloads
					first = false
				}
				if downloads != -1 && downloads < min {
					rpiece, rblock, min = k, block, downloads
				}
			}
		}
	}
	if !first && min < MAX_PIECE_REQUESTS {
		pd.Add(addr, rpiece, rblock)
		return
	}
	err = os.NewError("No available block found")
	return
}