|  | @@ -31,88 +31,21 @@
 | 
	
		
			
				|  |  |  #include <unistd.h>
 | 
	
		
			
				|  |  |  #include <errno.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -SegmentMan::SegmentMan():totalSize(0),
 | 
	
		
			
				|  |  | +SegmentMan::SegmentMan():bitfield(0),
 | 
	
		
			
				|  |  | +			 totalSize(0),
 | 
	
		
			
				|  |  |  			 isSplittable(true), 
 | 
	
		
			
				|  |  |  			 downloadStarted(false),
 | 
	
		
			
				|  |  |  			 dir("."),
 | 
	
		
			
				|  |  |  			 errors(0),
 | 
	
		
			
				|  |  | -			 splitter(NULL),
 | 
	
		
			
				|  |  | -			 diskWriter(NULL) {
 | 
	
		
			
				|  |  | +			 diskWriter(0) {
 | 
	
		
			
				|  |  |    logger = LogFactory::getInstance();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  SegmentMan::~SegmentMan() {
 | 
	
		
			
				|  |  | -  if(splitter != NULL) {
 | 
	
		
			
				|  |  | -    delete splitter;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if(diskWriter != NULL) {
 | 
	
		
			
				|  |  | -    delete diskWriter;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  delete bitfield;
 | 
	
		
			
				|  |  | +  delete diskWriter;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void SegmentMan::unregisterId(int cuid) {
 | 
	
		
			
				|  |  | -  for(Segments::iterator itr = segments.begin(); itr != segments.end(); itr++) {
 | 
	
		
			
				|  |  | -    if((*itr).cuid == cuid) {
 | 
	
		
			
				|  |  | -      cuid = 0;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -bool SegmentMan::getSegment(Segment& seg, int cuid) {
 | 
	
		
			
				|  |  | -  //Segment s = { 0, 0, 0, false };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if(segments.empty()) {
 | 
	
		
			
				|  |  | -    logger->debug(string("assign new segment { sp = 0, ep = "+(totalSize == 0 ? "0" : Util::llitos(totalSize-1))+" } to cuid "+Util::llitos(cuid)).c_str());
 | 
	
		
			
				|  |  | -    //seg = { cuid, 0, totalSize == 0 ? 0 : totalSize-1, 0, false };
 | 
	
		
			
				|  |  | -    seg.cuid = cuid;
 | 
	
		
			
				|  |  | -    seg.sp = 0;
 | 
	
		
			
				|  |  | -    seg.ep = totalSize == 0 ? 0 : totalSize-1;
 | 
	
		
			
				|  |  | -    seg.ds = 0;
 | 
	
		
			
				|  |  | -    seg.speed = 0;
 | 
	
		
			
				|  |  | -    seg.finish = false;
 | 
	
		
			
				|  |  | -    segments.push_back(seg);
 | 
	
		
			
				|  |  | -    return true;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  for(Segments::iterator itr = segments.begin(); itr != segments.end(); itr++) {
 | 
	
		
			
				|  |  | -    if((*itr).cuid == cuid && !(*itr).finish) {
 | 
	
		
			
				|  |  | -//       logger->debug("return an existing segment { "
 | 
	
		
			
				|  |  | -// 		    "sp = "+Util::ulitos((*itr).sp)+", "+
 | 
	
		
			
				|  |  | -// 		    "ep = "+Util::ulitos((*itr).ep)+", "
 | 
	
		
			
				|  |  | -// 		    "ds = "+Util::ulitos((*itr).ds)+" } to "+
 | 
	
		
			
				|  |  | -// 		    "cuid "+Util::ulitos((*itr).cuid));
 | 
	
		
			
				|  |  | -      seg = *itr;
 | 
	
		
			
				|  |  | -      return true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if(!isSplittable) {
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  for(Segments::iterator itr = segments.begin(); itr != segments.end(); itr++) {
 | 
	
		
			
				|  |  | -    Segment& s = *itr;
 | 
	
		
			
				|  |  | -    if(s.finish) {
 | 
	
		
			
				|  |  | -      continue;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if(s.cuid == 0) {
 | 
	
		
			
				|  |  | -      s.cuid = cuid;
 | 
	
		
			
				|  |  | -      seg = s;
 | 
	
		
			
				|  |  | -      return true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return splitter->splitSegment(seg, cuid, segments);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -void SegmentMan::updateSegment(const Segment& segment) {
 | 
	
		
			
				|  |  | -  for(Segments::iterator itr = segments.begin(); itr != segments.end(); itr++) {
 | 
	
		
			
				|  |  | -    if((*itr).cuid == segment.cuid && 
 | 
	
		
			
				|  |  | -       (*itr).sp == segment.sp &&
 | 
	
		
			
				|  |  | -       (*itr).ep == segment.ep) {
 | 
	
		
			
				|  |  | -      *itr = segment;
 | 
	
		
			
				|  |  | -      break;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  } 
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  bool SegmentMan::segmentFileExists() const {
 | 
	
		
			
				|  |  |    if(!isSplittable) {
 | 
	
		
			
				|  |  |      return false;
 | 
	
	
		
			
				|  | @@ -144,10 +77,6 @@ void SegmentMan::load() {
 | 
	
		
			
				|  |  |  			segFilename.c_str(), strerror(errno));
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    logger->info(MSG_LOADED_SEGMENT_FILE);
 | 
	
		
			
				|  |  | -  for(Segments::iterator itr = segments.begin(); itr != segments.end();
 | 
	
		
			
				|  |  | -      itr++) {
 | 
	
		
			
				|  |  | -    (*itr).cuid = 0;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void SegmentMan::save() const {
 | 
	
	
		
			
				|  | @@ -161,8 +90,32 @@ void SegmentMan::save() const {
 | 
	
		
			
				|  |  |      if(fwrite(&totalSize, sizeof(totalSize), 1, segFile) < 1) {
 | 
	
		
			
				|  |  |        throw string("writeError");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    for(Segments::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
 | 
	
		
			
				|  |  | -      if(fwrite(&*itr, sizeof(Segment), 1, segFile) < 1) {
 | 
	
		
			
				|  |  | +    int segmentLength = bitfield->getBlockLength();
 | 
	
		
			
				|  |  | +    if(fwrite(&segmentLength, sizeof(segmentLength), 1, segFile) < 1) {
 | 
	
		
			
				|  |  | +      throw string("writeError");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(bitfield) {
 | 
	
		
			
				|  |  | +      int bitfieldLength = bitfield->getBitfieldLength();
 | 
	
		
			
				|  |  | +      if(fwrite(&bitfieldLength, sizeof(bitfieldLength), 1, segFile) < 1) {
 | 
	
		
			
				|  |  | +	throw string("writeError");
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if(fwrite(bitfield->getBitfield(), bitfield->getBitfieldLength(),
 | 
	
		
			
				|  |  | +		1, segFile) < 1) {
 | 
	
		
			
				|  |  | +	throw string("writeError");
 | 
	
		
			
				|  |  | +      }					 
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      int i = 0;
 | 
	
		
			
				|  |  | +      if(fwrite(&i, sizeof(i), 1, segFile) < 1) {
 | 
	
		
			
				|  |  | +	throw string("writeError");
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    int usedSegmentCount = usedSegmentEntries.size();
 | 
	
		
			
				|  |  | +    if(fwrite(&usedSegmentCount, sizeof(usedSegmentCount), 1, segFile) < 1) {
 | 
	
		
			
				|  |  | +      throw string("writeError");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
 | 
	
		
			
				|  |  | +	itr != usedSegmentEntries.end(); itr++) {
 | 
	
		
			
				|  |  | +      if(fwrite(&itr->segment, sizeof(Segment), 1, segFile) < 1) {
 | 
	
		
			
				|  |  |  	throw string("writeError");
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -189,16 +142,35 @@ void SegmentMan::read(FILE* file) {
 | 
	
		
			
				|  |  |    if(fread(&totalSize, sizeof(totalSize), 1, file) < 1) {
 | 
	
		
			
				|  |  |      throw string("readError");
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  while(1) {
 | 
	
		
			
				|  |  | +  int segmentSize;
 | 
	
		
			
				|  |  | +  if(fread(&segmentSize, sizeof(segmentSize), 1, file) < 1) {
 | 
	
		
			
				|  |  | +    throw string("readError");
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  int bitfieldLength;
 | 
	
		
			
				|  |  | +  if(fread(&bitfieldLength, sizeof(bitfieldLength), 1, file) < 1) {
 | 
	
		
			
				|  |  | +    throw string("readError");
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if(bitfieldLength > 0) {
 | 
	
		
			
				|  |  | +    initBitfield(segmentSize, totalSize);
 | 
	
		
			
				|  |  | +    unsigned char* savedBitfield = new unsigned char[bitfield->getBitfieldLength()];
 | 
	
		
			
				|  |  | +    if(fread(savedBitfield, bitfield->getBitfieldLength(), 1, file) < 1) {
 | 
	
		
			
				|  |  | +      delete [] savedBitfield;
 | 
	
		
			
				|  |  | +      throw string("readError");
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      bitfield->setBitfield(savedBitfield, bitfield->getBitfieldLength());
 | 
	
		
			
				|  |  | +      delete [] savedBitfield;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  int segmentCount;
 | 
	
		
			
				|  |  | +  if(fread(&segmentCount, sizeof(segmentCount), 1, file) < 1) {
 | 
	
		
			
				|  |  | +    throw string("readError");
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  while(segmentCount--) {
 | 
	
		
			
				|  |  |      Segment seg;
 | 
	
		
			
				|  |  |      if(fread(&seg, sizeof(Segment), 1, file) < 1) {
 | 
	
		
			
				|  |  | -      if(ferror(file)) {
 | 
	
		
			
				|  |  | -	throw string("readError");
 | 
	
		
			
				|  |  | -      } else if(feof(file)) {
 | 
	
		
			
				|  |  | -	break;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +      throw string("readError");
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    segments.push_back(seg);
 | 
	
		
			
				|  |  | +    usedSegmentEntries.push_back(SegmentEntry(0, seg));
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -213,15 +185,14 @@ void SegmentMan::remove() const {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  bool SegmentMan::finished() const {
 | 
	
		
			
				|  |  | -  if(!downloadStarted || segments.size() == 0) {
 | 
	
		
			
				|  |  | +  if(!downloadStarted) {
 | 
	
		
			
				|  |  |      return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  for(Segments::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
 | 
	
		
			
				|  |  | -    if(!(*itr).finish) {
 | 
	
		
			
				|  |  | -      return false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +  if(!bitfield) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  return true;
 | 
	
		
			
				|  |  | +  assert(bitfield);
 | 
	
		
			
				|  |  | +  return bitfield->isAllBitSet();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void SegmentMan::removeIfFinished() const {
 | 
	
	
		
			
				|  | @@ -230,19 +201,219 @@ void SegmentMan::removeIfFinished() const {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -long long int SegmentMan::getDownloadedSize() const {
 | 
	
		
			
				|  |  | -  long long int size = 0;
 | 
	
		
			
				|  |  | -  for(Segments::const_iterator itr = segments.begin(); itr != segments.end(); itr++) {
 | 
	
		
			
				|  |  | -    size += (*itr).ds;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  return size;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  void SegmentMan::init() {
 | 
	
		
			
				|  |  |    totalSize = 0;
 | 
	
		
			
				|  |  |    isSplittable = false;
 | 
	
		
			
				|  |  |    downloadStarted = false;
 | 
	
		
			
				|  |  |    errors = 0;
 | 
	
		
			
				|  |  | -  segments.clear();
 | 
	
		
			
				|  |  | +  //segments.clear();
 | 
	
		
			
				|  |  | +  usedSegmentEntries.clear();
 | 
	
		
			
				|  |  | +  delete bitfield;
 | 
	
		
			
				|  |  | +  peerStats.clear();
 | 
	
		
			
				|  |  |    diskWriter->closeFile();
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void SegmentMan::initBitfield(int segmentLength, long long int totalLength) {
 | 
	
		
			
				|  |  | +  this->bitfield = new BitfieldMan(segmentLength, totalLength);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class FindSegmentEntryByIndex {
 | 
	
		
			
				|  |  | +private:
 | 
	
		
			
				|  |  | +  int index;
 | 
	
		
			
				|  |  | +public:
 | 
	
		
			
				|  |  | +  FindSegmentEntryByIndex(int index):index(index) {}
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  bool operator()(const SegmentEntry& entry) {
 | 
	
		
			
				|  |  | +    return entry.segment.index == index;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class FindSegmentEntryByCuid {
 | 
	
		
			
				|  |  | +private:
 | 
	
		
			
				|  |  | +  int cuid;
 | 
	
		
			
				|  |  | +public:
 | 
	
		
			
				|  |  | +  FindSegmentEntryByCuid(int cuid):cuid(cuid) {}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  bool operator()(const SegmentEntry& entry) {
 | 
	
		
			
				|  |  | +    return entry.cuid == cuid;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +Segment SegmentMan::checkoutSegment(int cuid, int index) {
 | 
	
		
			
				|  |  | +  logger->debug("Attach segment#%d to CUID#%d.", index, cuid);
 | 
	
		
			
				|  |  | +  bitfield->setUseBit(index);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
 | 
	
		
			
				|  |  | +					 usedSegmentEntries.end(),
 | 
	
		
			
				|  |  | +					 FindSegmentEntryByIndex(index));
 | 
	
		
			
				|  |  | +  Segment segment;
 | 
	
		
			
				|  |  | +  if(itr == usedSegmentEntries.end()) {
 | 
	
		
			
				|  |  | +    segment = Segment(index, bitfield->getBlockLength(index),
 | 
	
		
			
				|  |  | +		       bitfield->getBlockLength());
 | 
	
		
			
				|  |  | +    SegmentEntry entry(cuid, segment);
 | 
	
		
			
				|  |  | +    usedSegmentEntries.push_back(entry);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    (*itr).cuid = cuid;
 | 
	
		
			
				|  |  | +    segment = (*itr).segment;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  logger->debug("index=%d, length=%d, segmentLength=%d, writtenLength=%d",
 | 
	
		
			
				|  |  | +		segment.index, segment.length, segment.segmentLength,
 | 
	
		
			
				|  |  | +		segment.writtenLength);
 | 
	
		
			
				|  |  | +  return segment;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool SegmentMan::onNullBitfield(Segment& segment, int cuid) {
 | 
	
		
			
				|  |  | +  if(usedSegmentEntries.size() == 0) {
 | 
	
		
			
				|  |  | +    segment = Segment(0, 0, 0);
 | 
	
		
			
				|  |  | +    usedSegmentEntries.push_back(SegmentEntry(cuid, segment));
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    SegmentEntries::iterator uitr = find_if(usedSegmentEntries.begin(),
 | 
	
		
			
				|  |  | +					    usedSegmentEntries.end(),
 | 
	
		
			
				|  |  | +					    FindSegmentEntryByCuid(cuid));
 | 
	
		
			
				|  |  | +    if(uitr == usedSegmentEntries.end()) {
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      segment = uitr->segment;
 | 
	
		
			
				|  |  | +      return true;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool SegmentMan::getSegment(Segment& segment, int cuid) {
 | 
	
		
			
				|  |  | +  if(!bitfield) {
 | 
	
		
			
				|  |  | +    return onNullBitfield(segment, cuid);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  SegmentEntries::iterator uitr = find_if(usedSegmentEntries.begin(),
 | 
	
		
			
				|  |  | +					  usedSegmentEntries.end(),
 | 
	
		
			
				|  |  | +					  FindSegmentEntryByCuid(cuid));
 | 
	
		
			
				|  |  | +  if(uitr != usedSegmentEntries.end()) {
 | 
	
		
			
				|  |  | +    segment = uitr->segment;
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  int index = bitfield->getSparseMissingUnusedIndex();
 | 
	
		
			
				|  |  | +  if(index == -1) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    segment = checkoutSegment(cuid, index);
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool SegmentMan::getSegment(Segment& segment, int cuid, int index) {
 | 
	
		
			
				|  |  | +  if(!bitfield) {
 | 
	
		
			
				|  |  | +    return onNullBitfield(segment, cuid);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if(index < 0 || bitfield->countBlock() <= index) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if(bitfield->isBitSet(index) || bitfield->isUseBitSet(index)) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    segment = checkoutSegment(cuid, index);
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool SegmentMan::updateSegment(int cuid, const Segment& segment) {
 | 
	
		
			
				|  |  | +  if(segment.isNull()) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
 | 
	
		
			
				|  |  | +					 usedSegmentEntries.end(),
 | 
	
		
			
				|  |  | +					 FindSegmentEntryByCuid(cuid));
 | 
	
		
			
				|  |  | +  if(itr == usedSegmentEntries.end()) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    (*itr).segment = segment;
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +class CancelSegment {
 | 
	
		
			
				|  |  | +private:
 | 
	
		
			
				|  |  | +  int cuid;
 | 
	
		
			
				|  |  | +  BitfieldMan* bitfield;
 | 
	
		
			
				|  |  | +public:
 | 
	
		
			
				|  |  | +  CancelSegment(int cuid, BitfieldMan* bitfield):cuid(cuid),
 | 
	
		
			
				|  |  | +						 bitfield(bitfield) {}
 | 
	
		
			
				|  |  | +  
 | 
	
		
			
				|  |  | +  void operator()(SegmentEntry& entry) {
 | 
	
		
			
				|  |  | +    if(entry.cuid == cuid) {
 | 
	
		
			
				|  |  | +      bitfield->unsetUseBit(entry.segment.index);
 | 
	
		
			
				|  |  | +      entry.cuid = 0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void SegmentMan::cancelSegment(int cuid) {
 | 
	
		
			
				|  |  | +  if(bitfield) {
 | 
	
		
			
				|  |  | +    for_each(usedSegmentEntries.begin(), usedSegmentEntries.end(),
 | 
	
		
			
				|  |  | +	     CancelSegment(cuid, bitfield));
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    usedSegmentEntries.clear();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool SegmentMan::completeSegment(int cuid, const Segment& segment) {
 | 
	
		
			
				|  |  | +  if(segment.isNull()) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if(bitfield) {
 | 
	
		
			
				|  |  | +    bitfield->unsetUseBit(segment.index);
 | 
	
		
			
				|  |  | +    bitfield->setBit(segment.index);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    initBitfield(option->getAsInt(PREF_SEGMENT_SIZE), segment.writtenLength);
 | 
	
		
			
				|  |  | +    bitfield->setAllBit();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  SegmentEntries::iterator itr = find_if(usedSegmentEntries.begin(),
 | 
	
		
			
				|  |  | +					 usedSegmentEntries.end(),
 | 
	
		
			
				|  |  | +					 FindSegmentEntryByCuid(cuid));
 | 
	
		
			
				|  |  | +  if(itr == usedSegmentEntries.end()) {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    usedSegmentEntries.erase(itr);
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool SegmentMan::hasSegment(int index) const {
 | 
	
		
			
				|  |  | +  if(bitfield) {
 | 
	
		
			
				|  |  | +    return bitfield->isBitSet(index);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +long long int SegmentMan::getDownloadLength() const {
 | 
	
		
			
				|  |  | +  long long int dlLength = 0;
 | 
	
		
			
				|  |  | +  if(bitfield) {
 | 
	
		
			
				|  |  | +    dlLength += bitfield->getCompletedLength();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  for(SegmentEntries::const_iterator itr = usedSegmentEntries.begin();
 | 
	
		
			
				|  |  | +      itr != usedSegmentEntries.end(); itr++) {
 | 
	
		
			
				|  |  | +    dlLength += itr->segment.writtenLength;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return dlLength;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void SegmentMan::registerPeerStat(const PeerStatHandle& peerStat) {
 | 
	
		
			
				|  |  | +  PeerStatHandle temp = getPeerStat(peerStat->getCuid());
 | 
	
		
			
				|  |  | +  if(!temp.get()) {
 | 
	
		
			
				|  |  | +    peerStats.push_back(peerStat);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int SegmentMan::calculateDownloadSpeed() const {
 | 
	
		
			
				|  |  | +  int speed = 0;
 | 
	
		
			
				|  |  | +  for(PeerStats::const_iterator itr = peerStats.begin();
 | 
	
		
			
				|  |  | +      itr != peerStats.end(); itr++) {
 | 
	
		
			
				|  |  | +    const PeerStatHandle& peerStat = *itr;
 | 
	
		
			
				|  |  | +    if(peerStat->getStatus() == PeerStat::ACTIVE) {
 | 
	
		
			
				|  |  | +      speed += peerStat->calculateDownloadSpeed();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return speed;
 | 
	
		
			
				|  |  |  }
 |